Django Rest Framework ограничение уникального поля на массиве

Итак, я пытаюсь сделать конечную точку, в которую я вставляю список объектов.
Моя проблема заключается в поведении и реакции при вставке дубликатов.

Я хочу добиться следующего:

  1. Отправить дублирующий внешний_ид(ы) свинца в ответ на ошибку
  2. Вставьте любой другой не дублированный объект

Я почти уверен, что эту логику (для ответа и поведения) можно реализовать в модификации метода serializer.is_valid()... но прежде чем делать это, я хотел узнать, есть ли у кого-нибудь опыт работы с подобными запросами... Может быть, есть "чистый" способ сделать это, сохранив уникальную валидацию в модели.


Данные об ответе OK:

[
  {
    "external_id": "1", 
    "phone_number": "1234567890"
  }
]

Данные для запроса FAIL (1 дублируется, но 2 должен быть вставлен. Ожидается ответ типа "external_id" : "id 1 дублируется"):

[
  {
    "external_id": "1", 
    "phone_number": "1234567890"
  },
  {
    "external_id": "2", 
    "phone_number": "2234567890"
  }
]

models.py

class Lead(models.Model):
    external_id = models.CharField(max_length=20, unique=True)
    phone_number = models.CharField(max_length=50)

serializers.py

class LeadSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Lead
        fields = '__all__'

    def create(self, validated_data):
        lead = Lead.objects.create(**validated_data)
        log.info(f"Lead created: {lead.import_queue_id}")
        return lead

views.py

class LeadView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    @extend_schema(description="Insert campaign data", request=LeadSerializer(many=True), responses=None, tags=["Leads"])
    def post(self, request):
        serializer = LeadSerializer(data=request.data, many=True)

        valid = serializer.is_valid()
        if serializer.is_valid():
            serializer.save()
            return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
        else:
            return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

Вы можете настроить поведение списка объектов через list_serializer_class опцию в мета-классе. Например, так:

class LeadListSerializer(serializers.ListSerializer):
    def validate(self, data):
       items = list(map(lambda x: x['phone_number'], data))
       if len(set(items)) == len(items)):
           return super().validate(data)
       raise ValidationError()
       
class LeadSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Lead
        fields = '__all__'
        list_serializer_class = LeadListSerializer
Вернуться на верх