У меня есть модель "MyModel" со многими полями, и я хотел бы обновить поле "статус" с помощью метода PATCH. Я использую представления на основе классов. Есть ли способ реализовать PATCH?
Как очистить одно поле с помощью Django Rest Framework?
Ответ 1
Сериализаторы разрешают частичные обновления, указав partial=True
при инициализации serialzer. Вот как PATCH
запросы обрабатываются по умолчанию в общих представлениях.
serializer = CommentSerializer(comment, data=request.data, partial=True)
Это позволит вам обновлять отдельные поля в сериализаторе или все поля, если вы хотите, без каких-либо ограничений стандартного запроса PUT
.
Ответ 2
Как Кевин Браун заявил, что вы можете использовать partial=True
, который chefarov прояснил красиво.
Я просто хотел бы исправить их и сказать, что вы можете использовать generics свободно, в зависимости от используемого вами метода HTTP:
-
Если вы используете HTTP-метод PATCH, как заданный, вы получаете его из коробки. Вы можете увидеть
UpdateModelMixin
код дляpartial_update
:def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs)
-
Для любого метода HTTP, отличного от PATCH, это можно выполнить, просто переопределив метод
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)
…
Итак, если вы переопределите функцию get_serializer
, вы можете фактически переопределить частичный аргумент и заставить его быть истинным.
Обратите внимание, что если вы хотите, чтобы он был частичным только для некоторых методов HTTP, это затрудняет этот подход.
Я использую djangorestframework == 3.5.3
Ответ 3
Кажется, он поддерживается из коробки. В браузере API перейдите на страницу описания модели, внизу рядом с вкладкой HTML Form
нажмите Raw data
, удалите все из строки JSON, кроме поля ID и поля, которое вы хотите изменить, и нажмите PATCH
, Выполняется частичное обновление PATCH
.
Я использую djangorestframework==3.2.4
, и мне не нужно было ничего делать с моими представлениями и сериализаторами, чтобы включить это.
В этом примере мы обновляем поле 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 преуспел. Я думаю, что это приведет к тому, что люди будут многократно нажимать флажок для медленных соединений.
Ответ 4
Я некоторое время боролся с этим, но это очень простая реализация, использующая общие представления или комбинацию общих представлений и миксинов.
В случае использования общего представления обновления (generics.UpdateAPIView) просто используйте следующий код, убедившись, что тип запроса - PATCH:
class UpdateUser(generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
Нет ничего другого!
Если вы используете обновление mixin (mixins.UpdateModelMixin) в сочетании с общим представлением (generics.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)
Второй пример более сложный, показывая вам, как переопределить поле запроса и поиска, но код, на который вы должны обратить внимание, - это функция патча.