代码之家  ›  专栏  ›  技术社区  ›  Jim

修复“列已存在”Django迁移错误?

  •  6
  • Jim  · 技术社区  · 7 年前

    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
    

    Travel类继承自Activities类:

    # 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有关。用户或同一模型文件中的另一个类。我读了一篇文章 Tips for Building High-Quality Django Apps at Scale 最近,作者在文章中说,如果你有跨应用程序的外键,那么在运行迁移时可能会遇到问题,所以问题可能与此有关。我可以在活动模块中重新创建“Country”类,但这不会很枯燥。我不知道如何解决这个问题。

    4 回复  |  直到 7 年前
        1
  •  32
  •   Alasdair    7 年前

    如果 travel.country 字段已存在于数据库中,则无法运行迁移。您可以使用 --fake

    ./manage.py migrate activities 0002_auto_20170731_1939 --fake
    
        2
  •  1
  •   sebtheiler    3 年前

    如果您正在使用自定义迁移,并且由于错误而仅部分运行了迁移,则可能会出现此错误。

    要解决这个问题,可以将该列放到DB shell中( ./manage.py dbshell ):

    ALTER TABLE myapp_mymodel DROP COLUMN your_column;
    

    只有在列没有数据并且是在创建自定义迁移时意外创建的情况下,才能执行此操作。这将删除列中的所有数据,如果不这样做,则可能会破坏DJANGO。

        3
  •  0
  •   stPhoenix    7 年前

    正如阿拉斯代尔所说,您不能覆盖现有列。当我做这样的事情时——必须删除表并用clear migrate重新创建新表。

        4
  •  0
  •   FLEUR MATIP    7 年前

    related_name=“(app_label)s_%(class)s_related”,

    related\u query\u name=“(app\u label)s_%(class)ss”,