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 模型迁移操作不适用的主要内容,如果未能解决你的问题,请参考以下文章

Django 迁移中的操作错误

Django 1.6 到 1.11 Admin.py 迁移

Python-Django模型迁移用户数据库模型的迁移(对其他数据库迁移同样适用)!!!

Django 1.11 使用命令makemigrations命令无法执行表修改动作

如何在 Django 迁移中创建 GIN 索引

扩展 Django 1.11 用户模型