Django AutoField错误迁移“id”字段

时间:2015-06-23 17:15:48

标签: django django-models

我有一个非常简单的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.

运行 manage.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”字段。

快速而肮脏的解决方案是 - 进行此迁移。哪个应该在dev机器上本地工作,但可能导致其他环境(test / staging / prod)上的迁移错误。

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

不确定原因,但我的主要问题是 - 当这种迁移没有任何需要时,重置模型或迁移状态并将其返回到上一个状态的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

好的,为此找到了可行的解决方法。

添加&#34; id&#34;字段声明为原始迁移,因此不再报告为丢失。

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的真实模型进行比较。

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