Ошибка при миграции 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
Вернуться на верх