修复'列已经存在'Django迁移错误?

问题描述:

我收到的时候我尝试运行Django的迁移命令“关系的列已经存在”错误:修复'列已经存在'Django迁移错误?

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 

的旅游类从活动类继承:

# 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... 

国家由外键引用的类位于另一个模块中。它本质上是一个查找表将包含每个国家代码(简称)和 名称:

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

我看不出有什么出格的迁移普通的文件不是事实,其他的有两种迁移活动文件(我不太明白):

# 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... 
    ] 

我不明白为什么我得到这个错误。我注意到在声明外键关系的其他模型中我没有这个问题。但是,在所有这些模型中,外键关系都是auth.models.User或同一模型文件中的另一个类。我最近阅读了一篇文章Tips for Building High-Quality Django Apps at Scale,其中作者说如果您有跨应用程序外键,则可能会遇到迁移问题,所以问题可能与此有关。我可以在活动模块内重新创建'Country'类,但这不会干。我不知道如何解决这个问题。

+0

您是否为现有数据库创建了迁移,或者您刚启动了此项目? – Alasdair

+0

这是对现有数据库的迁移。迁移曾经运行,但现在他们没有。奇怪的是,我有一段时间没有改变相关的活动模型。 – William

如果travel.country字段已存在于数据库中,则无法运行迁移。您可以使用--fake选项将迁移标记为已应用,而不实际运行SQL。

./manage.py migrate activities 0002_auto_20170731_1939 --fake 
+0

谢谢。迁移无误地运行。但我仍然很想知道为什么我要获得可交换的依赖关系指令和两个迁移文件0001_initial_.py和0002_auto _....你认为这是因为我有一个外键作为文章I穿越应用程序边界参考建议?您是否在使用您编写的Django应用程序时遇到此问题?谢谢! – William

+0

我不知道为什么你在这种情况下结束了两次迁移。这可能是因为你的应用程序具有循环依赖关系。我不确定我是否同意链接文章的建议,以获得单个单一应用程序。你可能会发现[这个谈话](https://skillsmatter.com/skillscasts/7129-encapsulated-django-keeping-your-apps-small-focused-and-free-of-circular-dependencies)有趣。 – Alasdair

+0

呃。我刚刚注意到,当我运行最后一次迁移时,不同模型中的新列没有添加(因为我正在迁移活动应用程序,所以我会这样做)。所以我改变了名字,迫使Django看到了变化,而且确实如此。但是当我运行'makemigrations'时,Django抱怨说它无法通过旧名称找到新列。这些迁移令人生气。 – William

正如Alasdair所说,您无法覆盖现有列。当我做出这样的事情时 - 必须删除表格并用清晰的迁移重新创建新表格。

为一个ForeignKey或抽象类​​ManyToManyField,添加相关的名字是这样的: related_name = “%(app_label)■_%(类)s_related”,

如果您还使用related_query_name,添加此: related_query_name =“%(app_label)s _%(class)ss”,