Ich versuche, partial_update
mit Django Rest Framework zu implementieren.
Warum müssen wir partial = True angeben?
Nach meinem Verständnis könnten wir das Demo-Objekt in der partial_update
-Methode leicht aktualisieren. Was ist der Zweck davon?
Was enthält die serialisierte Variable?
Was ist in der Variable serialized
in der Methode partial_update
enthalten? Ist das ein Demoobjekt? Welche Funktion wird hinter den Kulissen aufgerufen?
Viewset
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)
Serializer
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
Für teilweise Aktualisierung -PATCHhttp-Methode
Für full update -SETZEN SIEhttp-Methode
Bei einer Aktualisierung mit DRF sollten Sie Anforderungsdaten senden, die Werte für alle (erforderlichen) Felder enthalten. Dies ist zumindest der Fall, wenn die Anforderung über die HTTP-Methode PUT erfolgt. Nach meinem Verständnis möchten Sie eines oder zumindest nicht alle Modellinstanzfelder aktualisieren. In diesem Fall stellen Sie eine Anfrage mit der http-Methode PATCH. Django Rest Framework (DRF) kümmert sich sofort darum.
Beispiel (mit 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/
Nur eine kurze Notiz, da es so aussieht, als hätte noch niemand darauf hingewiesen:
serialized = DemoSerializer(request.user, data=request.data, partial=True)
Das erste Argument von DemoSerializer sollte eine Demo-Instanz sein, kein Benutzer (zumindest wenn Sie DRF 3.6.2 wie mich verwenden).
Ich weiß nicht, was Sie versuchen, aber dies ist ein funktionierendes Beispiel:
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
Ich mache das teilweise Update und dann mache ich andere Dinge, benenne my_func und übergebe den aktuellen Benutzer und die Demo-Instanz bereits aktualisiert.
Hoffe das hilft.
Ich hatte ein Problem, bei dem meine Multi-Attribut-/Feldvalidierung in einem rest_framework-Serialisierer mit einer POST/resources/-Anforderung arbeitete, aber mit einer PATCH/resources/-Anforderung fehlschlug. Im PATCH-Fall ist dies fehlgeschlagen, da nur nach Werten in der angegebenen Variable attrs
gesucht und nicht auf Werte in self.instance
zurückgegriffen wurde. Das Hinzufügen einer Methode get_attr_or_default
für diesen Fallback scheint zu funktionieren:
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)