with instalar framework espaƱol con django django-rest-framework

instalar - django rest framework with django 2



ActualizaciĆ³n parcial de Django Rest Framework (5)

Olvidaste serializer.save()

Puedes terminarlo de la siguiente manera. . .

class DemoViewSet(viewsets.ModelViewSet): serializer_class = DemoSerializer def partial_update(self, request, pk=None): serializer = DemoSerializer(request.user, data=request.data, partial=True) serializer.save() serializer.is_valid(raise_exception=True) return Response(serializer.data)

Además, no debería tener que anular el método de actualización en el serializador.

Estoy tratando de implementar partial_update con Django Rest Framework pero necesito una aclaración porque estoy atascado.

  1. ¿Por qué necesitamos especificar parcial = Verdadero?
    En mi entendimiento, podríamos actualizar fácilmente el objeto Demo dentro del método partial_update . ¿Cuál es el propósito de esto?

  2. ¿Qué hay dentro de la variable serializada?
    ¿Qué hay dentro de la variable serialized en el método partial_update ? ¿Es ese un objeto de demostración? ¿Qué función se llama detrás de escena?

  3. ¿Cómo terminaría uno la implementación aquí?

Conjunto de vistas

class DemoViewSet(viewsets.ModelViewSet): serializer_class = DemoSerializer def partial_update(self, request, pk=None): serialized = DemoSerializer(request.user, data=request.data, partial=True) return Response(status=status.HTTP_202_ACCEPTED)

Serializador

class DemoSerializer(serializers.ModelSerializer): class Meta: model = Demo fields = ''__all__'' def update(self, instance, validated_data): print ''this - here'' demo = Demo.objects.get(pk=instance.id) Demo.objects.filter(pk=instance.id)/ .update(**validated_data) return demo


Para actualización parcial - método PATCH http

Para actualización completa - método PUT http

Al realizar una actualización con DRF, debe enviar datos de solicitud que incluyen valores para todos los campos (requeridos). Este es al menos el caso cuando la solicitud se realiza a través del método http PUT. Por lo que entiendo, desea actualizar uno o al menos no todos los campos de instancia de modelo. En este caso realice una solicitud con el método PATCH http. Django resto framework (DRF) se encargará de fuera de la caja.

Ejemplo (con token auth):

curl -i -X PATCH -d ''{"name":"my favorite banana"}'' -H "Content-Type: application/json" -H ''Authorization: Token <some token>'' http://localhost:8000/bananas/


Solo una nota rápida, ya que parece que nadie ya ha señalado esto:

serialized = DemoSerializer(request.user, data=request.data, partial=True)

El primer argumento de DemoSerializer debería ser una instancia de Demo, no un usuario (al menos si usa DRF 3.6.2 como yo).

No sé lo que estás tratando de hacer, pero este es un ejemplo práctico:

def partial_update(self, request, *args, **kwargs): response_with_updated_instance = super(DemoViewSet, self).partial_update(request, *args, **kwargs) Demo.objects.my_func(request.user, self.get_object()) return response_with_updated_instance

Realizo la actualización parcial y luego hago otras cosas llamando a my_func y pasando el usuario actual y la instancia de demostración ya actualizada.

Espero que esto ayude.


Tengo la misma pregunta que usted antes, pero cuando profundizo en el código fuente de rest_framework, obtuve los siguientes hallazgos, espero que ayude:

Para la pregunta 1)

Esta pregunta está relacionada con los verbos HTTP .

PUT : El método PUT reemplaza todas las representaciones actuales del recurso de destino con la carga útil de solicitud.

PARCHE : el método PATCH se utiliza para aplicar modificaciones parciales a un recurso.

En términos generales, partial se usa para verificar si los campos del modelo son necesarios para realizar la validación de campos cuando el cliente envía datos a la vista.

Por ejemplo, tenemos un modelo de Book como este, por favor, tenga en cuenta que tanto el name como el name author_name son obligatorios (no nulos y no están en blanco).

class Book(models.Model): name = models.CharField(''name of the book'', max_length=100) author_name = models.CharField(''the name of the author'', max_length=50) # Create a new instance for testing Book.objects.create(name=''Python in a nut shell'', author_name=''Alex Martelli'')

Para algunos escenarios, es posible que solo necesitemos actualizar parte de los campos del modelo, por ejemplo, solo necesitamos actualizar el campo de name en el Book . Entonces, para este caso, el cliente solo enviará el campo de name con un nuevo valor a la vista. Los datos enviados por el cliente pueden verse así:

{"pk": 1, name: "PYTHON IN A NUT SHELL"}

Pero es posible que haya notado que nuestra definición de modelo no permite que author_name esté en blanco. Así que tenemos que usar partial_update lugar de update . Por lo tanto, el marco de trabajo restante no realizará la verificación de validación de campos para los campos que faltan en los datos de solicitud.

Para fines de prueba, puede crear dos vistas para la update y la update partial_update , y obtendrá una mejor comprensión de lo que acabo de decir.

Ejemplo:

vistas.py

from rest_framework.generics import GenericAPIView from rest_framework.mixins import UpdateModelMixin from rest_framework.viewsets import ModelViewSet from rest_framework import serializers class BookSerializer(serializers.ModelSerializer): class Meta: model = Book class BookUpdateView(GenericAPIView, UpdateModelMixin): '''''' Book update API, need to submit both `name` and `author_name` fields At the same time, or django will prevent to do update for field missing '''''' queryset = Book.objects.all() serializer_class = BookSerializer def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) class BookPartialUpdateView(GenericAPIView, UpdateModelMixin): '''''' You just need to provide the field which is to be modified. '''''' queryset = Book.objects.all() serializer_class = BookSerializer def put(self, request, *args, **kwargs): return self.partial_update(request, *args, **kwargs) urls.py

urlpatterns = patterns('''', url(r''^book/update/(?P<pk>/d+)/$'', BookUpdateView.as_view(), name=''book_update''), url(r''^book/update-partial/(?P<pk>/d+)/$'', BookPartialUpdateView.as_view(), name=''book_partial_update''), )

Datos a enviar

{"pk": 1, name: "PYTHON IN A NUT SHELL"}

Cuando envíe el json anterior a /book/update/1/ , obtendrá el siguiente error con HTTP_STATUS_CODE = 400:

{ "author_name": [ "This field is required." ] }

Pero cuando envía el json anterior a /book/update-partial/1/ , obtendrá HTTP_STATUS_CODE = 200 con la siguiente respuesta,

{ "id": 1, "name": "PYTHON IN A NUT SHELL", "author_name": "Alex Martelli" }

Para la pregunta 2)

serialized es un objeto que envuelve la instancia del modelo como un objeto serializable. y puede usar este serializado para generar una cadena JSON simple con serialized.data .

Para la pregunta 3)

Creo que puedes responderte cuando hayas leído la respuesta anterior, y deberías haber sabido cuándo usar la update y cuándo usar la update partial_update .

Si todavía tiene alguna pregunta, no dude en preguntar. Acabo de leer parte del marco fuente de las odas de descanso, y es posible que no haya entendido muy bien algunos términos y, por favor, indíquelo cuando esté mal ...


Tuve un problema en el que mi validación de múltiples atributos / campo en un serializador rest_framework funcionaba con un POST / resources / request pero fallaba con un PATCH / resources / request. Falló en el caso de PATCH porque solo buscaba valores en los attrs los attrs proporcionados y no retrocedía a los valores en la self.instance . La adición de un método get_attr_or_default para hacer ese repliegue parece haber funcionado:

class EmailSerializer(serializers.ModelSerializer): def get_attr_or_default(self, attr, attrs, default=''''): """Return the value of key ``attr`` in the dict ``attrs``; if that is not present, return the value of the attribute ``attr`` in ``self.instance``; otherwise return ``default``. """ return attrs.get(attr, getattr(self.instance, attr, '''')) def validate(self, attrs): """Ensure that either a) there is a body or b) there is a valid template reference and template context. """ existing_body = self.get_attr_or_default(''body'', attrs).strip() if existing_body: return attrs template = self.get_attr_or_default(''template'', attrs) templatecontext = self.get_attr_or_default(''templatecontext'', attrs) if template and templatecontext: try: render_template(template.data, templatecontext) return attrs except TemplateRendererException as err: raise serializers.ValidationError(str(err)) raise serializers.ValidationError(NO_BODY_OR_TEMPLATE_ERROR_MSG)