Django迁移RunPython无法调用模型方法

问题描述 投票:38回答:4

我正在使用RunPython方法创建数据迁移。但是,当我尝试在对象上运行方法时,没有定义。是否可以使用RunPython调用模型上定义的方法?

django django-models django-migrations
4个回答
37
投票

迁移中不提供模型方法,包括数据迁移。

但是有一些解决方法,它应该与调用模型方法非常相似。您可以在迁移中定义模拟要使用的模型方法的函数。

如果你有这个方法:

class Order(models.Model):
    '''
    order model def goes here
    '''

    def get_foo_as_bar(self):
        new_attr = 'bar: %s' % self.foo
        return new_attr

您可以在迁移脚本中编写函数,如:

def get_foo_as_bar(obj):
    new_attr = 'bar: %s' % obj.foo
    return new_attr


def save_foo_as_bar(apps, schema_editor):
    old_model = apps.get_model("order", "Order")

    for obj in old_model.objects.all():
        obj.new_bar_field = get_foo_as_bar(obj)
        obj.save()

然后在迁移中使用它:

class Migration(migrations.Migration):

    dependencies = [
        ('order', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(save_foo_as_bar)
    ]

这样迁移就可以了。将会有一些重复的代码,但这并不重要,因为数据迁移应该是在应用程序的特定状态下的一次操作。


14
投票

你是否像文档中所说的那样打电话给你的模型?

def combine_names(apps, schema_editor):
    # We can't import the Person model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Person = apps.get_model("yourappname", "Person")
    for person in Person.objects.all():
        person.name = "%s %s" % (person.first_name, person.last_name)
        person.save()

Data-Migration因为此时您无法直接导入模型:

from yourappname.models import Person

更新

内部Django代码在此文件中django / db / migrations / state.py django.db.migrations.state.ModelState#construct_fields

def construct_fields(self):
    "Deep-clone the fields using deconstruction"
    for name, field in self.fields:
        _, path, args, kwargs = field.deconstruct()
        field_class = import_string(path)
        yield name, field_class(*args, **kwargs)

在“假”模型实例中只有克隆字段:

MyModel.__module__ = '__fake__'

Github Django


4
投票

从Django 1.8开始,您可以通过在模型管理器上设置use_in_migrations = True来使模型管理器可用于迁移。见migrations documentation


0
投票

精美的印刷品放在Historical Models

因为序列化任意Python代码是不可能的,所以这些历史模型将没有您定义的任何自定义方法。

当我第一次在迁移过程中遇到它并且没有阅读细则时,这是一个令人惊讶的因为它似乎与他们的Design Philosophy相矛盾(在模型周围添加功能)

© www.soinside.com 2019 - 2024. All rights reserved.