我有一个非常简单的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 字段。
不确定原因,但我的主要问题是 - 当这种迁移没有任何需要时,重置模型或迁移状态并将其返回到上一个状态的正确方法是什么?
答案 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的真实模型进行比较。
调整原始迁移解决了这个问题。感谢所有参与讨论的人。