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.
¿Por qué necesitamos especificar parcial = Verdadero?
En mi entendimiento, podríamos actualizar fácilmente el objeto Demo dentro del métodopartial_update
. ¿Cuál es el propósito de esto?¿Qué hay dentro de la variable serializada?
¿Qué hay dentro de la variableserialized
en el métodopartial_update
? ¿Es ese un objeto de demostración? ¿Qué función se llama detrás de escena?- ¿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.pyfrom 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)