web-dev-qa-db-ger.com

Django Rest Framework teilweise aktualisiert

Ich versuche, partial_update mit Django Rest Framework zu implementieren.

  1. 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?

  2. 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?

  3. Wie würde man die Implementierung hier beenden?

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
30
intelis

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/
24
Gooshan

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.

0

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)
0
jrwdunham