Ошибка при миграции Django с 3.1 на 3.2 при копировании экземпляров моделей
Я пытаюсь обновить Django с 3.1 до 3.2, и одна из ошибок, с которой я столкнулся, - это конечные точки, которые у меня дублируют ресурсы и связанные с ними модели.
В этом примере:
@action(
detail=True,
methods=['POST'],
name='Duplicate one resource',
url_name='duplicate',
url_path='duplicate',
)
@transaction.atomic
def duplicate(self, request, pk=None):
foo = self.get_object() # gets foo
foo_bars = foo.foo_bars.all() # gets a queryset of FooBar
new_name = self.append_copy_suffix(foo.name)
new_foo = foo.copy_instance(name=new_name) # code below
print(foo, new_foo)
FooBar.objects.bulk_create(
[FooBar(foo=new_foo, bar=foo_bar.bar, stuff=foo_bar.stuff) for foo_bar in foo_bars]
)
return Response(self.get_serializer(new_foo).data, status=status.HTTP_201_CREATED)
def copy_instance(self, **kwargs):
"""
Method to copy a model instance
More info here: https://docs.djangoproject.com/en/3.1/topics/db/queries/#copying-model-instances
:param kwargs: additional parameters to update
:return: the duplicated resource
"""
new_resource = self
new_resource.pk = None
for k, v in kwargs.items():
setattr(new_resource, k, v)
new_resource._state.adding = True
new_resource.save()
return new_resource
В Django 3.1 это работает довольно хорошо, но в Django 3.2 связанные ресурсы почему-то не создаются.
То, что я заметил при отладке и печати значений:
- Когда я печатаю
foo
иnew_foo
, они одинаковые (new_foo
). foo_bars
пуст. Возможно, потому чтоfoo
иnew_foo
- это одно и то же передbulk_create
, аfoo_bars
- это просто набор запросов, который еще не был выполнен.- Мне нужно привести кверисет к списку(), чтобы получить существующие и создать новые FooBars.
Что мне нужно исправить, чтобы это работало?
Что касается этой проблемы, я попробовал подход Сергея Фоменко и это сработало. Спасибо за помощь :)
def copy_instance(self, **kwargs):
new_resource = copy.deepcopy(self)
new_resource.pk = None
for k, v in kwargs.items():
setattr(new_resource, k, v)
new_resource._state.adding = True
new_resource.save()
return new_resource