Django 1.11 模型迁移操作不适用
Posted
技术标签:
【中文标题】Django 1.11 模型迁移操作不适用【英文标题】:Django 1.11 Model Migration Operations doesn't apply 【发布时间】:2019-04-21 21:21:52 【问题描述】:我在迁移中的操作已执行,而数据库中没有任何关于付款人字段的操作。
这是我的模型:
class User(AbstractBaseUser, PermissionsMixin, WithCsvImportMixin):
first_name = models.CharField(_('first name'), max_length=30, blank=False)
last_name = models.CharField(_('last name'), max_length=30, blank=False)
email = models.EmailField(_('email address'),
unique=True, blank=False)
external_id = models.CharField(_('external id'), db_index=True, max_length=50, unique=True, blank=False, null=True)
is_staff = models.BooleanField(_('staff status'), default=False)
is_active = models.BooleanField(_('active'), default=True)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
payer = models.CharField(_('payer'), max_length=50, blank=False, default='')
第一次关于payer字段的迁移:
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-11-15 21:58
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authenticate', '0012_auto_20181112_1631'),
]
operations = [
migrations.AddField(
model_name='user',
name='payer',
field=models.CharField(default='', max_length=50, verbose_name='payer'),
),
]
这是执行的,但结果似乎没有应用于数据库:
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-11-15 22:01
from django.db import migrations, transaction
from xxx.authenticate.models import User # The xxx is here to replace the actual application name
def create_payer_names(apps, schema_editor):
with transaction.atomic():
for user in User.objects.all():
if user.external_id != "":
user.payer = user.external_id
user.save()
class Migration(migrations.Migration):
dependencies = [
('authenticate', '0013_user_payer'),
]
operations = [
migrations.RunPython(create_payer_names, migrations.RunPython.noop, atomic=True),
]
我的数据库已经填充,每个用户都有一个external_id
>>> from xxx.authenticate.models import User
>>> for item in User.objects.all():
... print(item.external_id)
...
043819FZAFR
762944FZAFR
285895FZAFR
671800FZAFR
924618FZAFR
068805FZAFR
232544FZAFR
130978FZAFR
412568FZAFR
600003FZAFR
254624FZAFR
417745FZAFR
068280FZAFR
031971FZAFR
141936FZAFR
>>>
这是之前迁移的空结果:
>>> for item in User.objects.all():
... print(item.payer)
...
>>>
这是命令的输出:manage.py showmigrations
authenticate
[X] 0001_initial
[X] 0002_auto_20171103_1722
[X] 0003_auto_20171109_1206
[X] 0004_auto_20180329_1049
[X] 0005_auto_20180507_1123
[X] 0006_user_by_pass_generates_invoice
[X] 0007_auto_20180524_1732
[X] 0008_auto_20180530_1525
[X] 0009_auto_20180801_1644
[X] 0010_user_payment
[X] 0011_remove_user_payment
[X] 0012_auto_20181112_1631
[X] 0013_user_payer
[X] 0014_auto_20181115_2301
当我这样做时:
./manage.py migrate authenticate 0014
输出如下:
Running migrations:
No migrations to apply.
有人可以向我解释我做错了什么以及为什么没有按预期应用迁移操作吗?
【问题讨论】:
我看不出问题出在哪里,但您绝对不应该从您的实际模型代码中导入用户;在迁移中,您应该始终获得冻结版本,所以User = apps.get_model('authenticate', 'User')
。
@DanielRoseman 我已经在这样做了,我只是为这篇 SO 帖子更改了它,以便更容易理解!
【参考方案1】:
在迁移中,您应该使用apps.get_model
来获取User
模型。有关详细信息,请参阅有关 [数据迁移] 的文档。
def create_payer_names(apps, schema_editor):
User = apps.get_model('authentication', 'User')
with transaction.atomic():
...
showmigrations 的输出显示迁移 0014 已被应用。这就是您收到No migrations to apply
消息的原因。
[X] 0014_auto_20181115_2301
您可以通过先伪装回 0013 迁移来重新运行 0014 迁移。
./manage.py migrate --fake authenticate 0013
./manage.py migrate authenticate 0014
【讨论】:
非常感谢,它实际上工作得很好!我不知道--fake
它适用于我的本地环境。当我要推送到另一个环境时,我需要执行相同的命令还是会自动应用它?
我不确定您希望自动应用哪个命令。我们使用了--fake
,因为showmigrations
表明0014
已被应用,而您想要撤消它以便重新运行迁移0014。您也应该在其他环境中运行showmigrations
,并决定是否或不是你需要使用--fake
。
感谢您的见解!以上是关于Django 1.11 模型迁移操作不适用的主要内容,如果未能解决你的问题,请参考以下文章
Python-Django模型迁移用户数据库模型的迁移(对其他数据库迁移同样适用)!!!