Django Rest Framework ограничение уникального поля на массиве
Итак, я пытаюсь сделать конечную точку, в которую я вставляю список объектов.
Моя проблема заключается в поведении и реакции при вставке дубликатов.
Я хочу добиться следующего:
- Отправить дублирующий внешний_ид(ы) свинца в ответ на ошибку
- Вставьте любой другой не дублированный объект
Я почти уверен, что эту логику (для ответа и поведения) можно реализовать в модификации метода 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