J'essaie de mettre en œuvre partial_update
avec Django Rest Framework mais j'ai besoin de précisions car je suis bloqué.
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?
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?
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
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/
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.
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)