POST список словарей и обновление или создание - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь заставить мою django-rest-framework принимать список диктов для обновления или создания множества объектов за один вызов API.

Моя модель:

class Order(models.Model):

    internal_id = models.CharField(max_length=500, unique=True)
    external_id = models.CharField(max_length=500, blank=True, null=True, unique=True)
    status = models.CharField(max_length=500, blank=True, null=True)

Myseriallizer:

class SimpleOrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

Мой взгляд:

class CreateListMixin():
    def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True
        return super().get_serializer(*args, **kwargs)





class OrderViewSet(CreateListMixin, viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = SimpleOrderSerializer
    lookup_field = 'internal_id'

Этот код прекрасно работает, если я помещаю в POST список словарей с новыми значениями internal_id, но если я включаю уже существующее значениеЯ хочу обновить этот объект. Возможно ли это с django-rest-framework?

1 Ответ

0 голосов
/ 04 октября 2019

Да, это возможно, но вам придется предоставить свой собственный метод create на сериализаторе. Я бы посоветовал вам прочитать о части «Настройка множественного создания» документации .

Реализация по умолчанию для создания нескольких объектов заключается в простом вызове .create() для каждого элементав списке. Если вы хотите настроить это поведение, вам нужно настроить метод .create() в классе ListSerializer, который используется при передаче many=True.

Поэтому вам нужно создатьSimpleOrderListSerializer, который определяет желаемое поведение, например:

class SimpleOrderListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        orders = []
        for item in validated_data:
            # Assuming your "identifying" set of fields is only `internal_id`
            internal_id = item.pop('internal_id')
            order, created = Order.objects.update_or_create(
                internal_id=internal_id,
                defaults=item,
            )
            orders.append(order)
        return orders

И затем определите этот сериализатор как сериализатор списка по умолчанию для SimpleOrderSerializer:

class SimpleOrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        list_serializer_class = SimpleOrderListSerializer
        fields = '__all__'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...