RunPython
メソッドを使用してデータ移行を作成しています。ただし、オブジェクトでメソッドを実行しようとすると、何も定義されません。 RunPython
を使用してモデルで定義されたメソッドを呼び出すことは可能ですか?
モデルのメソッドは、データの移行を含む移行では利用できません。
ただし、回避策があります。これは、モデルメソッドの呼び出しと非常によく似ています。使用するモデルメソッドを模倣する移行内の関数を定義できます。
この方法がある場合:
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)
]
これにより、移行が機能します。コードの少しの繰り返しがありますが、データ移行はアプリケーションの特定の状態での1回限りの操作であるため、問題ではありません。
ドキュメンテーションで述べたようにモデルを呼び出しましたか?
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__'
Django 1.8の場合、use_in_migrations = True
モデルマネージャー。 migrations documentation を参照してください。
細かい活字は Historical Models
任意のPythonコードをシリアル化することは不可能であるため、これらの履歴モデルには、定義したカスタムメソッドがありません。
移行時に最初に遭遇し、細かい活字を読まなかったのは非常に驚きでした 設計哲学 (モデルの周りに機能を追加する)