web-dev-qa-db-ja.com

Django移行RunPythonがモデルメソッドを呼び出せない

RunPythonメソッドを使用してデータ移行を作成しています。ただし、オブジェクトでメソッドを実行しようとすると、何も定義されません。 RunPythonを使用してモデルで定義されたメソッドを呼び出すことは可能ですか?

40
user2954587

モデルのメソッドは、データの移行を含む移行では利用できません。

ただし、回避策があります。これは、モデルメソッドの呼び出しと非常によく似ています。使用するモデルメソッドを模倣する移行内の関数を定義できます。

この方法がある場合:

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回限りの操作であるため、問題ではありません。

37
chhantyal

ドキュメンテーションで述べたようにモデルを呼び出しましたか?

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

14
Azman0101

Django 1.8の場合、use_in_migrations = Trueモデルマネージャー。 migrations documentation を参照してください。

4
Ryan Knight

細かい活字は Historical Models

任意のPythonコードをシリアル化することは不可能であるため、これらの履歴モデルには、定義したカスタムメソッドがありません。

移行時に最初に遭遇し、細かい活字を読まなかったのは非常に驚きでした 設計哲学 (モデルの周りに機能を追加する)

1
user2829759