Как исправить одно поле с помощью 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.