【问题标题】:Django AutoField wrong migration for "id" fieldDjango AutoField 错误迁移“id”字段
【发布时间】:2015-06-23 17:15:48
【问题描述】:

我有一个非常简单的 Django 模型:

class MyModel(models.Model):
    user = models.ForeignKey(User)
    somestring = models.CharField(
        max_length=250
    )
   ... some other string fields...

模型中没有声明“id”字段,所以它有Django自动分配的主键。

初始迁移如下所示:

migrations.CreateModel(
    name='MyModel',
    fields=[
         ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
         ('somestring', models.CharField(max_length=250))
         ... some other string fields...
    ],
    options={},
    bases=(models.Model,),
),

申请成功,数据库表包含如下字段:

- id   <== autogenerated 
- user
- somestring
 etc...

有时我开始收到类似的消息

Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

运行 ma​​nage.py makemigrations 后,它产生了非常奇怪的迁移:

$ ./manage.py makemigrations
You are trying to add a non-nullable field 'id' to mymodel without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now()
>>> 
Please enter some code, or 'exit' (with no quotes) to exit.
>>> ''
Migrations for 'myapp':
  0036_auto_20150623_1535.py:
    - Add field id to mymodel

看起来像这样:

class Migration(migrations.Migration):

    dependencies = [
        ('foo', 'bar'),
    ]

    operations = [
        migrations.AddField(
            model_name='mymodel',
            name='id',                 <== !!!
            field=models.AutoField(auto_created=True, primary_key=True, default='', serialize=False, verbose_name='ID'),
            preserve_default=False,
        ),
    ]

但是这种迁移没有意义,并且肯定会失败,因为适当的数据库表中已经有“id”字段。

快速而肮脏的解决方案是 --fake 这个迁移。这应该在开发机器上本地工作,但可能导致其他环境(测试/登台/生产)上的迁移错误。

看起来模型的旧/新字段状态计算不正确,因此“id”未包含在旧模型中但已包含在新模型中,因此 django 决定 应添加 id 字段。

不确定原因,但我的主要问题是 - 当不需要进行此类迁移时,重置模型或迁移状态并将其返回到前一个状态的正确方法是什么?

【问题讨论】:

  • 该表确实存在吗?你检查过桌子吗?表中有记录吗?
  • 表存在,有记录
  • 我不确定,但只有在影响数据库当前状态的任何更改时才会创建迁移文件。在我看来,这种迁移只有两个可能的原因。 1.- 一个 django 错误和 2.- 文件中的更改。如果您使用 git,我建议您搜索文件中的更改。
  • 感谢@MikeVelazco,我最近对该文件进行了几次更改,但与“id”字段无关,所以不确定可能是什么原因。
  • 您的任何模型字段是否碰巧有primary_key=True?看起来与 questionbug 非常相似。

标签: django django-models


【解决方案1】:

好的,找到了一个可行的解决方法。

在原始迁移中添加了“id”字段声明,因此不再报告为丢失。

migrations.CreateModel(
    name='MyModel',
    fields=[
!!===>   ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
         ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
         ('somestring', models.CharField(max_length=250))
         ... some other string fields...
    ],
    options={},
    bases=(models.Model,),
),

此更改不会应用于我们已经进行此迁移的环境,新环境应从一开始就获得正确的数据库表结构。

TIL: Django 不使用 SQL 从 DB 中获取当前模型状态,而是创建模型的模拟并将迁移应用到该模拟,直到它获得最新版本的模型可用的迁移操作。然后将重建的模型与 models.py 中的真实模型进行比较。

调整原始迁移解决了该问题。感谢所有参与讨论的人。

【讨论】:

    猜你喜欢
    • 2015-06-09
    • 2016-02-01
    • 2015-02-17
    • 2018-09-03
    • 2019-07-27
    • 1970-01-01
    • 2016-02-14
    • 2012-08-06
    • 2015-02-09
    相关资源
    最近更新 更多