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)
Очевидно, что это не обновление записи. Просто удаляется существующая и создается новая.