Миграции Django RunPython не могут вызывать методы модели
Я создаю миграцию данных с помощью RunPython
метод. Однако, когда я пытаюсь запустить метод на объекте, никто не определен. Можно ли вызвать метод, определенный на модели, используя RunPython
?
3 ответов
методы модели недоступны в миграциях, включая миграции данных.
есть обходной путь, который должен быть очень похож на вызов методов модели. Вы можете определить функции внутри миграций, которые имитируют те методы модели, которые вы хотите использовать.Если бы у вас был этот метод:
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)
]
таким образом миграция будет работать. Будет немного повторения кода, но это не имеет значения, потому что миграция данных должна быть однократной операцией в определенном состоянии приложения.
вы назвали свою модель, как сказано в документации ?
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()
Переноса Данных Потому что на данный момент, Вы не можете импортировать модель прямо :
from yourappname.models import Person
обновление
внутренний код Django находится в этом файле django/db/migrations/state.py Джанго.децибел.миграции.государство.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
на модель менеджера. Вижу документация по миграции.