web-dev-qa-db-fra.com

Mise à jour partielle de Django Rest Framework

J'essaie de mettre en œuvre partial_update avec Django Rest Framework mais j'ai besoin de précisions car je suis bloqué.

  1. Pourquoi devons-nous spécifier partial = True?
    D'après ce que j'ai compris, nous pourrions facilement mettre à jour un objet Demo à l'intérieur de la méthode partial_update. Quel est le but de ceci?

  2. Qu'y a-t-il à l'intérieur d'une variable sérialisée?
    Qu'y a-t-il à l'intérieur de la variable serialized dans la méthode partial_update? Est-ce un objet de démonstration? Quelle fonction est appelée dans les coulisses?

  3. Comment finirait-on la mise en oeuvre ici?

Vues

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)

Sérialiseur

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

Pour la méthode partial update -PATCHhttp

Pour la méthode full update -PUThttp

Lors de la mise à jour avec DRF, vous êtes censé envoyer des données de demande qui incluent des valeurs pour tous les champs (obligatoires). C'est du moins le cas lorsque la requête est effectuée via la méthode http PUT. D'après ce que j'ai compris, vous souhaitez mettre à jour un ou tous les champs d'instance de modèle. Dans ce cas, faites une requête avec la méthode http PATCH. Le cadre de repos de Django (DRF) s’occupe de lui hors de la boîte.

Exemple (avec authentification de jeton): 

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

Juste une petite note car il semble que personne ne l’a déjà signalé:

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

Le premier argument de DemoSerializer devrait être une instance de démonstration, pas un utilisateur (du moins si vous utilisez DRF 3.6.2 comme moi).

Je ne sais pas ce que vous essayez de faire, mais voici un exemple concret:

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

Je fais la mise à jour partielle puis j'appelle my_func en transmettant l'utilisateur actuel et l'instance de démonstration déjà mise à jour.

J'espère que cela t'aides.

0
Sergio Morstabilini

J'ai eu un problème où ma validation multi-attribut/champ dans un sérialiseur rest_framework fonctionnait avec un POST/resources/request mais échouant avec un PATCH/resources/request. Il a échoué dans le cas PATCH car il ne cherchait que les valeurs dans le attrs dict fourni et ne revenait pas aux valeurs dans self.instance. Ajouter une méthode get_attr_or_default pour faire ce repli semble avoir fonctionné:

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