Note that there are some explanatory texts on larger screens.

plurals
  1. PONew Django South migration breaks an earlier one
    primarykey
    data
    text
    <h1>A. Summary:</h1> <p><em>After successfully running a new migration (adds a new column to an existing table), an earlier migration that operates on the same table (<code>0010</code>) fails with:</em></p> <pre><code>Creating test database for alias 'default'... Got an error creating the test database: database "test_ymc_platform" already exists Type 'yes' if you would like to try deleting the test database 'test_ymc_platform', or 'no' to cancel: </code></pre> <p><em>And when I respond with <code>yes</code>:</em></p> <pre><code>Error in migration: ymc:0010_auto__add_field_user_registered_at DatabaseError: column users.publisher_id does not exist LINE 1: ...dress", "users"."gender", "users"."developer_id", "users"."publisher_id... ^ </code></pre> <p><br/> <br/></p> <h1>B. Details:</h1> <p><br/></p> <h2>1. How are these migrations run?</h2> <p>They are run by Django's unit tests. <a href="http://south.readthedocs.org/en/latest/unittests.html" rel="nofollow">As you know, South runs "every migration every time you run your tests."</a></p> <p><br/></p> <h2>2. Migration History</h2> <p>I have (among others) three tables: <code>users</code>, <code>games</code> and <code>publishers</code>. Up until migration <code>0025</code>, they had nothing to do with one another. In migration <code>0025</code>, I add a foreign key where <code>users.publisher_id</code> and <code>games.publisher_id</code> reference <code>publishers</code>.</p> <p>When I created and ran <code>0025</code>, I was at <code>0024</code> and everything migrated successfully. Then I ran my unit tests and got the prompt and error message described above. So <code>0025</code>--><code>0024</code> works, but <code>0009</code>--><code>0010</code> fails.</p> <p>My current migration history is like this:</p> <pre><code>$ ./manage.py migrate ymc --list ymc (*) 0001_initial ... (*) 0004_auto__add_field_user_gender ... (*) 0010_auto__add_field_user_registered_at ... (*) 0025_auto__add_field_user_publisher__add_field_game_publisher </code></pre> <p><em><code>0004</code> is included as a demonstration that South can run migrations on the <code>users</code> table without choking. Perhaps something is special about <code>0010</code>.</em></p> <p><br/></p> <h2>2. What does your model code for that new column look like?</h2> <p>I added <code>publisher_id</code> columns to both <code>users</code> and <code>games</code> like so:</p> <pre><code># Same for both 'users' and 'games' publisher = models.ForeignKey('ymc.Publisher', blank=True, null=True, default=None) </code></pre> <p><br/></p> <h2>3. What code did South generate?</h2> <p>Here's the existing migration that's started failing:</p> <h3><code>0010_auto__add_field_user_registered_at</code>:</h3> <pre><code>class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'User.registered_at' db.add_column('users', 'registered_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False) users = User.objects.all() for user in users: user.registered_at = user.joined_at user.save() def backwards(self, orm): # Deleting field 'User.registered_at' db.delete_column('users', 'registered_at') models = { ... 'ymc.user': { 'Meta': {'object_name': 'User', 'db_table': "'users'"}, 'access_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'access_token_expiry': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'developer': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['ymc.Developer']", 'null': 'True', 'blank': 'True'}), 'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), 'facebook_access_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'facebook_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'forgot_password_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'forgot_password_token_expiry': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'games': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ymc.Game']", 'null': 'True', 'through': "orm['ymc.UsersGames']", 'blank': 'True'}), 'gender': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'joined_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), 'registered_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'salt': ('django.db.models.fields.CharField', [], {'max_length': '128', 'unique': 'True', 'null': 'True', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), 'verified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) }, ... } </code></pre> <p><br/></p> <p>And here's the new migration that, while successfully applied, causes <code>0010</code> to choke.</p> <h3><code>0025_auto__add_field_user_publisher__add_field_game_publisher</code></h3> <pre><code>class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'User.publisher' db.add_column('users', 'publisher', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['ymc.Publisher'], null=True, blank=True), keep_default=False) # Adding field 'Game.publisher' db.add_column('games', 'publisher', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['ymc.Publisher'], null=True, blank=True), keep_default=False) def backwards(self, orm): # Deleting field 'User.publisher' db.delete_column('users', 'publisher_id') # Deleting field 'Game.publisher' db.delete_column('games', 'publisher_id') models = { ... 'ymc.user': { 'Meta': {'object_name': 'User', 'db_table': "'users'"}, 'access_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'access_token_expiry': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'developer': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['ymc.Developer']", 'null': 'True', 'blank': 'True'}), 'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), 'facebook_access_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'facebook_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'forgot_password_token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), 'forgot_password_token_expiry': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'games': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ymc.Game']", 'null': 'True', 'through': "orm['ymc.UsersGames']", 'blank': 'True'}), 'gender': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'joined_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), 'publisher': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['ymc.Publisher']", 'null': 'True', 'blank': 'True'}), 'registered_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), 'salt': ('django.db.models.fields.CharField', [], {'max_length': '128', 'unique': 'True', 'null': 'True', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'verified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) }, ... } </code></pre> <p><br/></p> <h2>4. What's the output if you run the tests with <code>--verbose=3</code>?</h2> <p>This:</p> <pre><code> ... &gt; ymc:0010_auto__add_field_user_registered_at = ALTER TABLE "users" ADD COLUMN "registered_at" timestamp with time zone NULL; [] = ALTER TABLE "users" ALTER COLUMN "registered_at" TYPE timestamp with time zone, ALTER COLUMN "registered_at" DROP NOT NULL, ALTER COLUMN "registered_at" DROP DEFAULT; [] Error in migration: ymc:0010_auto__add_field_user_registered_at - Sending post_syncdb signal for ymc: ['Game', 'UsersGames', 'User', 'Developer'] DatabaseError: column users.publisher_id does not exist LINE 1: ...dress", "users"."gender", "users"."developer_id", "users"."p... </code></pre> <p><br/></p> <h2>5. What have you tried?</h2> <ul> <li><p>Rolling everything back and trying again (exact same results).</p></li> <li><p>Wishing really hard that this is a dream.</p></li> <li><p>Man... other than that, not much. I'm super confused. I don't even understand where this error message is being generated:</p> <pre><code> LINE 1: ...dress", "users"."gender", "users"."developer_id", "users"."p... ^ Like, </code></pre> <p><code>LINE 1:</code> of what, right?</p></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload