首页 > 解决方案 > Django 1.11 模型迁移操作不适用

问题描述

我在迁移中的操作被执行,而数据库中没有发生任何关于付款人字段的事情。

这是我的模型:

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.

有人可以向我解释我做错了什么以及为什么没有按预期应用迁移操作吗?

标签: pythondjangopython-3.xdjango-migrations

解决方案


在迁移中,您应该使用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

推荐阅读