Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fix 'column already exists' Django Migration Error?

I'm getting a "column of relation already exists" error when I try to run the Django migrate command:

Operations to perform:
  Synchronize unmigrated apps: signin, django_rq, gis, staticfiles, admindocs, messages, pipeline, test_without_migrations, django_extensions
  Apply all migrations: profile, activities, contenttypes, # plus other modules...
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying activities.0002_auto_20170731_1939...Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 330, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/core/management/base.py", line 393, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/core/management/base.py", line 444, in execute
    output = self.handle(*args, **options)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 222, in handle
    executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 110, in migrate
    self.apply_migration(states[migration], migration, fake=fake, fake_initial=fake_initial)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 148, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 115, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 62, in database_forwards
    field,
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/contrib/gis/db/backends/postgis/schema.py", line 94, in add_field
    super(PostGISSchemaEditor, self).add_field(model, field)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 398, in add_field
    self.execute(sql, params)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 111, in execute
    cursor.execute(sql, params)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/utils.py", line 97, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/srv/http/example.com/venvs/4dc40e5fc12700640a30ae0f040aa07ffc8aa1c5/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column "country_id" of relation "travel" already exists

The Travel class inherits from the Activities class:

# activities/models.py
from profile.models import Country

class Activity(models.Model):
    host = models.ForeignKey(User)
    # other fields...

    class Meta:
        abstract = True

class Travel(Activity):
    start_date = models.DateField()
    country = models.ForeignKey(Country)
    # other fields...

The country class being referenced by the foreign key is in another module. It's essentially a lookup table that will contain a code (abbreviation) and name for each country:

# profile/models.py
class Country(models.Model):
    country_cd = models.CharField(max_length=2)
    descrip = models.CharField(max_length=50)

I don't see anything out of the ordinary in the migrations file other than the fact that there are two migration files for activities (which I don't quite understand):

# activities/migrations/0001_initial.py
class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Travel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=256)),
                # other fields but none that reference Country
            ],
            options={
                'db_table': 'travel',
            },
        ),
    ]

# activities/migrations/0002_auto_20170731_1939.py
class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('profile', '0001_initial'),
        ('activities', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='travel',
            name='country',
            field=models.ForeignKey(to='profile.Country'),
        ),
        migrations.AddField(
            model_name='travel',
            name='host',
            field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
        ),
        # other fields...
    ]

I don't understand why I'm getting this error. I've noticed that I don't have this problem in other models that declare foreign key relations. However,in all of those models either the foreign key relation is to auth.models.User or to another class within the same model file. I read an article Tips for Building High-Quality Django Apps at Scale recently in which the author said you can have problems running migrations if you have cross-app foreign keys, so maybe the problem is related to that. I could recreate the 'Country' class inside the activities module but that wouldn't be DRY. I'm not sure how to resolve this problem.

like image 947
Jim Avatar asked Aug 01 '17 18:08

Jim


2 Answers

If the travel.country field already exists in the database, then it isn't possible to run the migration. You can use the --fake option to mark the migration as applied, without actually running the SQL.

./manage.py migrate activities 0002_auto_20170731_1939 --fake
like image 154
Alasdair Avatar answered Nov 14 '22 05:11

Alasdair


If you are working with custom migrations and your migrations only partially ran because of an error, you might get this error.

To resolve it, you can drop the column in the DB shell (./manage.py dbshell):

ALTER TABLE myapp_mymodel DROP COLUMN your_column;

ONLY DO THIS IF THE COLUMN HAS NO DATA AND WAS ACCIDENTALLY CREATED WHEN YOU WERE CREATING A CUSTOM MIGRATION. THIS WILL ERASE ALL THE DATA IN THE COLUMN AND POSSIBLY SCREW UP DJANGO IF DONE OTHERWISE.

like image 43
user-124812948 Avatar answered Nov 14 '22 03:11

user-124812948