Различные действия над ресурсами одного типа в одном запросе с Django Rest Framework - PullRequest
0 голосов
/ 24 октября 2018

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

Я пришел к этой идее, читая: статья

Запрос на эту конечную точку будет выглядеть следующим образом:

[
  {
    "id": "ID1",
    "method": "DELETE"
  },
  {
    "id": "ID2",
    "method": "PATCH",
    "body": {"resource's": "data"}
  },
    {
        "method": "POST",
        "body": {"resource's": "data"}
    }
]

Давайте возьмем мои сериализаторы

class ActionResourceSerializer(serializers.Serializer):

    HTTP_METHODS = ('POST', 'PUT', 'PATCH', 'DELETE')
    pk = serializers.IntegerField(min_value=1, required=False)
    method = serializers.ChoiceField(choices=HTTP_METHODS, required=False)
    body = ResourceSerializer()

    def validate(self, attrs):
        pk = attrs.get('id')
        method = attrs.get('method')

        if method in ('PATCH', 'PUT', 'DELETE') and not pk:
            raise serializers.ValidationError({'id': f'This field is required for {method} method.'})

        if method in ('POST', 'PUT'):
            raise serializers.ValidationError({'body': f'This field is required for {method} method.'})

Во время написания кода я столкнулся с несколькими проблемами:

1частичный флаг в сериализаторах django.

По умолчанию ActionResourceSerializer будет иметь частичный флаг False.Дочерний ResourceSerializer для ActionResourceSerializer также «унаследует» флаг, поэтому во время проверки он вызовет исключения, касающиеся required fields.Нет простого способа изменить это поведение.

Из-за этой проблемы мне пришло в голову написать собственный класс Manager, который будет проходить через request.data, и выбрать подходящий сериализатор, соответствующий методупункт запроса.Поэтому для 'method = PATCH' он вызовет ActionResourceSerializer(data=data, partial=True), для method=PUT или 'method = POST' ActionResourceSerializer(data=data, instance=instance), а для 'DELETE' он просто найдет объект в БД и удалит его.Но я не уверен, что это хорошая идея.

Код pesudo менеджера будет выглядеть так:

class Manager:

    def __int__(self, data, instance):
        self.data = data
        self._errors = []

    @property
    def errors(self):
        return self._errors

    def is_valid(self):
        return not bool(self.errors)

    def _manage_departments(self):

        for item in self.data:
            method = item.get('method')
            if not method:
                self._errors.append({"method": ["This field is required."]})
                continue

            if method == 'PATCH':

                serialzier = ActionResourceSerializer(data=item, partial=True)

            elif method in ('PUT', 'POST'):
                serialzier = ActionResourceSerializer(data=item, partial=False)

Любое предложение, ребята?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...