Массовые, частичные обновления с Django Rest Framework - PullRequest
0 голосов
/ 03 ноября 2018

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

Я предполагаю, что это проблема маршрутизации. Мне нужен новый вид для обработки PATCH на / (а не /id/), но я уже не в себе.

Существующие ответы на этот вопрос не работают для 3.8, или, по крайней мере, не работает для меня. Что мне нужно сделать со следующим?

class ResourceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Resource
        fields = ('id', 'name', ...)
        read_only_fields = ('id',)

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

        return super().get_serializer(*args, **kwargs)

class ResourceViewSet(BulkMixin, viewsets.ModelViewSet):
    serializer_class = ResourceSerializer

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Я бы предложил не пытаться реализовать это самостоятельно. Рассмотрите возможность использования django-rest-framework-bulk . Он поддерживает массовые, частичные обновления и предоставляет сериализаторы, представления и маршрутизатор для упрощения настройки.

0 голосов
/ 03 ноября 2018

После ~ 10 часов, стуча головой об эту стену, я решил, что в правильном направлении может отойти на заднее сиденье, и я обойдусь с хакерским способом, который работает. Я добавил следующий gnarlfest в свой просмотр.

@action(methods=['patch'], detail=False)
def bulk_update(self, request):

    data = {  # we need to separate out the id from the data
        i['id']: {k: v for k, v in i.items() if k != 'id'}
        for i in request.data
    }

    for inst in self.get_queryset().filter(id__in=data.keys()):
        serializer = self.get_serializer(inst, data=data[inst.id], partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()

    return Response({})

Если я внесу исправление в список [{id: 123, otherfield: "abc"}, ...], это будет частичное обновление. Я вполне уверен, что это делает n + 1 запросов и что это было бы намного более эффективно в сыром ORM ... но сейчас, это бесконечно лучше, чем n запросов . Кроме того, если идентификатор отсутствует в наборе запросов, он будет передаваться вместо ошибок. Это работает для меня, но не для других.

Я назначу щедрость на этот вопрос через 48 часов, чтобы соблазнить хороших ответов.

...