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()
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)
如果你像我一样,因为得到错误ValueError: RunPython must be supplied with a callable而来到这里,这是因为你在函数的末尾放了"()",你在migrations.RunPython中给code赋值 错误,例如migrations.RunPython(code=do_something(), reverse=noop) 它应该是:migrations.RunPython(code=do_something, reverse=noop),不带()
7条答案
按热度按时间h43kikqp1#
模型方法在迁移(包括数据迁移)中不可用。
然而,有一种解决方法,它应该与调用模型方法非常相似,你可以在迁移中定义函数来模拟你想要使用的那些模型方法。
如果你有这个方法:
您可以在迁移脚本中编写如下函数:
然后在迁移中使用它:
迁移将以这种方式工作,虽然会有一些代码的重复,但这并不重要,因为数据迁移应该是应用程序特定状态下的一次性操作。
k97glaaz2#
你有没有像文档里说的那样调用你的模型?
数据迁移因为此时,您不能直接导入您的模型:
Django的内部代码在这个文件中django/db/migrations/www.example.com django. db. migrations. state. ModelState #construct_fieldsstate.py django.db.migrations.state.ModelState#construct_fields
只有字段是"假"模型示例中的克隆:
吉图布· Django
ufj5ltwl3#
在历史模型中打下了小字
因为不可能序列化任意的Python代码,所以这些历史模型将没有您定义的任何定制方法。
当我在迁移过程中第一次遇到它时,我感到非常惊讶,因为它似乎与他们的设计哲学(围绕模型添加功能)相矛盾,所以我没有阅读其中的小字。
odopli944#
从Django1.8开始,您可以通过在模型管理器上设置
use_in_migrations = True
来使模型管理器可用于迁移。6xfqseft5#
这并没有回答OP,但可能对某些人仍然有用。
不仅定制模型方法在迁移中不可用,其他模型属性也是如此,比如用于模型字段
choices
的类“常量”。在这个特定的边缘案例中,我们无法在迁移过程中直接访问选项的历史值,但是我们 * 可以 * 使用model _meta api从model字段获取历史值,因为这些值包含在迁移中。
以Django的
Student
为例:我们可以获得迁移中
Student.FRESHMAN
的历史值,如下所示:62lalag46#
当你有许多复杂的方法互相调用,并且你需要通过你的对象来使用它们时,这对我来说是很有用的:
首先将这些模型方法复制到迁移文件中
然后在迁移功能中:
khbbv19g7#
如果你像我一样,因为得到错误
ValueError: RunPython must be supplied with a callable
而来到这里,这是因为你在函数的末尾放了"()",你在migrations.RunPython
中给code
赋值错误,例如
migrations.RunPython(code=do_something(), reverse=noop)
它应该是:
migrations.RunPython(code=do_something, reverse=noop)
,不带()