Django Rest Framework - Сериализатор create_or_update дает IntegrityError: Unique Constraint Failed

У меня возникла проблема при использовании API для отправки обновления существующей записи.

Когда я отправляю API для новой записи, он работает отлично. Но когда я отправляю его для существующей записи, я хотел бы, чтобы он обновил текущую запись, но вместо этого он выдает ошибку целостности.

Мой Serializers.py выглядит следующим образом:


class PartSerializer(serializers.ModelSerializer):
    part = serializers.CharField()
    class Meta:
        model = DocumentRef
        fields = ('part', 'field1', 'field2', 'field3')

    def create(self, validated_data):
        part = Part.objects.get(part_number=validated_data['part'])
        validated_data['part'] = part
        return DocumentRef.objects.update_or_create(**validated_data)

Я пробовал изменить update_or_create на create или просто update, но это все равно сработает, только если запись еще не существует.

Модель, на которую он должен ссылаться, это DocumentRef, которая выглядит следующим образом:


class DocumentRef(models.Model):
    part = models.OneToOneField(Part, on_delete=models.CASCADE)
    field1 = models.FileField(upload_to='mcp/')
    field2 = models.FileField(upload_to='qcp/')
    field3 = models.FileField(upload_to='cus/')

Представление API, которое я использую, выглядит следующим образом:


class APIDetailTest(APIView):
    def get_object(self, pk):
        try:
            return DocumentRef.objects.get(pk=pk)
        except DocumentRef.DoesNotExist:
            return HttpResponse(status=status.HTTP_404_NOT_FOUND)

    def get(self, request, pk):
        part = self.get_object(pk)
        serializer = PartSerializer(part)
        return Response(serializer.data)

    def put(self, request, pk):
        part = self.get_object(pk)
        serializer = PartSerializer(part, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Edit: Changed create_or_update to update_or_create -- Just made this error in this post, in my code it was correct from the beginning.

Попробуйте использовать его с defaults и kwargs, пожалуйста, прочитайте здесь: django docs

Метод update_or_create пытается получить объект из базы данных на основе заданных kwargs. Если совпадение найдено, он обновляет поля переданные в словаре по умолчанию.

Вам нужно обновить запрос следующим образом

def create(self, validated_data):
    part = Part.objects.get(part_number=validated_data['part'])
    validated_data['part'] = part
    return DocumentRef.objects.update_or_create(defaults={'part': part}, **validated_data)

Это скорее обходной путь, чем ответ, но вы можете попробовать перехватить ошибку и обработать запрос по-другому.

примерно так:


def create(self, validated_data):
    ...
    try: 
        return DocumentRef.objects.create(**validated_data)
    except IntegrityError:
        DocumentRef.objects.filter(part=validated_data['part']).delete()
        return DocumentRef.objects.create(**validated_data)


Очевидно, что это не обновление записи. Просто удаляется существующая и создается новая.

Вернуться на верх