Как исправить одно поле с помощью Django Rest Framework?

У меня есть модель "MyModel" со многими полями, и я хотел бы обновить поле "статус" с помощью метода PATCH. Я использую представления на основе классов. Есть ли способ реализовать патч?

4 ответов


сериализаторы разрешить частичные обновления, указав partial=True при инициализации serialzer. Вот как!--7-->PATCH запросы обрабатываются по умолчанию в общий вид.

serializer = CommentSerializer(comment, data=request.data, partial=True)

Это позволит вам обновлять отдельные поля в сериализаторе или все поля, если вы хотите, без каких-либо ограничений стандарта PUT запрос.


As Кевин Браун заявил, что вы можете использовать partial=True, который chefarov красиво разъяснил.

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

  • если вы используете патч HTTP-метод, как спросил, Вы получаете его из коробки. Вы можете видеть UpdateModelMixin код partial_update:

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)
    
  • для любого метода HTTP отличается из патча это можно сделать, просто переопределив get_serializer метод следующим образом:

    def get_serializer(self, *args, **kwargs):
        kwargs['partial'] = True
        return super(YOUR_CLASS, self).get_serializer(*args, **kwargs)
    

это создаст сериализатор как частичный, а остальные генераторы будут работать как шарм без какого-либо ручного вмешательства в механизм update/partial_update.

под капотом

я использовал универсальный: generics.UpdateAPIView использует UpdateModelMixin, который имеет этот код:

def update(self, request, *args, **kwargs):
    partial = kwargs.pop('partial', False)
    instance = self.get_object()
    serializer = self.get_serializer(instance, data=request.data, partial=partial)
    …

Итак, если вы переопределяете the get_serializer функция, вы можете фактически переопределить частичный аргумент и заставить его быть истинным.

обратите внимание, что если вы хотите, чтобы он был частичным только для некоторых методов HTTP, это затрудняет этот подход.

я использую djangorestframework==3.5.3


кажется, что он поддерживается из коробки. В API браузера перейдите на страницу сведений о модели, расположенную внизу рядом с нажмите кнопку Raw data, удалите все из строки JSON, кроме поля ID и поля, которое вы хотите изменить, и нажмите PATCH. Частичное PATCH обновление выполняется.

я использую djangorestframework==3.2.4, и не пришлось ничего делать, чтобы мой ViewSets и сериализаторы для этого.

в этом exampe мы обновляем bool status_field поле модели, и я использую jquery 2.2.1. Добавьте в <head>:

<script src="{% static 'my_app/jquery.min.js' %}"></script>
<script>
$(document).ready(function(){
    var chk_status_field = $('#status_field');
    chk_status_field.click(function(){
        $.ajax({url: "{% url 'model-detail' your_rendering_context.id %}",
            type: 'PATCH', timeout: 3000, data: { status_field: this.checked }
        })
        .fail(function(){
            alert('Error updating this model instance.');
            chk_status_field.prop('checked', !chk_status_field.prop('checked'));
        });
    });
});
</script>

затем в <form>:

<input type="checkbox" id="status_field" {% if your_rendering_context.status_field %} 
    checked {% endif %} >

я решил разрешить флажок для изменения, а затем вернуть его в случае сбоя. Но вы могли бы заменить click С mousedown чтобы обновить значение флажка только после успешного вызова AJAX. Я думаю, что это приведет к тому, что люди будут неоднократно нажимать флажок для медленных соединений.


Я некоторое время боролся с этим, но это очень простая реализация с использованием общих представлений или комбинации общих представлений и mixins.

в случае использования общего представления обновления (generics.UpdateAPIView), просто используйте следующий код, убедившись, что тип запроса-PATCH:

class UpdateUser(generics.UpdateAPIView):

    queryset = User.objects.all()
    serializer_class = UserSerializer

больше ничего нет!

Если вы используете обновление mixin (mixins.UpdateModelMixin) в сочетании с общим представлением (дженерик.GenericAPIView), используйте следующий код, убедившись, что тип запроса-PATCH:

class ActivateUser(mixins.UpdateModelMixin, generics.GenericAPIView):

    serializer_class = UserSerializer
    model = User
    lookup_field = 'email'

    def get_queryset(self):
        queryset = self.model.objects.filter(active=False)
        return queryset

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

второй пример более сложный, показывающий, как переопределить поле queryset и lookup, но код, на который вы должны обратить внимание, - это функция patch.