Проверка существования записи при массовом POST'е с помощью Django REST Framework

У меня есть список словарей, который я разобрал на JSON с помощью json.dumps(). Теперь я хочу отправить эти данные в мою базу данных с помощью фреймворка Django REST.

# Example Data to POST
[
   {
      "key_1":"data_1",
      "key_2":"data_2",

   },
   {
      "key_1":"data_1",
      "key_2":"data_2",
   },
   {
      "key_1":"data_3",
      "key_2":"data_4",
   }
]

Если представить, что все записи уникальны (что не так в приведенном выше наборе данных), мы можем успешно выполнить пакетное POST этих данных с помощью:

# models.py
class data(models.Model):
    data_1 = models.CharField(max_length=64, blank=True, null=True)
    data_2 = models.CharField(max_length=64, blank=True, null=True)

    class Meta:
        unique_together = (( "data_1", "data_2"))

# serializers.py
class dataSerializer(serializers.ModelSerializer):
    class Meta:
        model = data
        fields = '__all__'

# views.py
class dataViewSet(viewsets.ModelViewSet):
    queryset=data.objects.all()
    serializer_class=dataSerializer
    filter_backends=[DjangoFilterBackend]
    filterset_fields=['key_1', 'key_2']

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=isinstance(request.data,list))
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

# Initiating the POST request
api_url="localhost:8000/app/api/"
requests.post(
        f"{api_url}data/", 
        data=my_json_serialised_data, 
        headers=headers
    )

Однако это не удастся, если некоторые записи уже существуют в базе данных ("поля должны быть уникальны вместе").

В соответствии с данными примера, записи в списке иногда уже будут присутствовать в базе данных, поэтому я хотел бы избежать дублирования POST'ов (на основе комбинации полей в модели; я указал unique_together, чтобы было ясно, какие поля).

Какой лучший DRF-способ проверки существования записи и, если она существует, пропускать ее, когда вы имеете дело с массовым POST? Должен ли я использовать viewsets.ModelViewSet и переопределить метод create() внутри этого класса? Или есть лучший подход? Я отметил, что существует несколько способов создания записей в DRF, поэтому я хочу получить ясность относительно лучшего подхода, когда мы имеем дело с партией данных, как в приведенном выше примере.

Для решения этой проблемы вы можете использовать custom list serializer, чтобы иметь возможность получить проверенные данные в виде списка, который затем будет поддерживать создание ваших data объектов массово, используя bulk_create.

Кроме того, вы можете игнорировать ошибки ограничений (например, уникальные ограничения в вашем случае) с помощью функций bulk_create ignore_conflicts:

В базах данных, которые поддерживают его (все, кроме Oracle), установка параметра ignore_conflicts в True указывает базе данных игнорировать неудачу вставки любых строк, которые не соответствуют ограничениям, таким как дублирование уникальных значений. Включение этого параметра отключает установку первичного ключа для каждого экземпляра модели (если база данных обычно поддерживает это).

.

Итак, в целом вы можете сделать что-то вроде:

class dataListSerializer(serializers.ListSerializer)
    def create(self, validated_data):
        return data.objects.bulk_create([
            data(**validated) for validated in validated_data
        ], ignore_conflicts=True)


class dataSerializer(serializers.ModelSerializer):
    class Meta:
        model = data
        fields = '__all__'
        list_serializer_class = dataListSerializer

Когда many=True отмечен в сериализаторе, create dataListSerializer будет использоваться вместо dataSerializer, который будет поддерживать вышеупомянутый create in bulk.

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