2015-11-22 6 views
5

ich Django REST-FrameworkWie kann request.data in django REST Rahmen ändern

request.data = '{"id": "10", "user": "tom"}' 

Ich möchte wie "age": "30" zusätzliche Attribut hinzufügen verwende, bevor es weiter wie

request.data = new_data 
    response = super().post(request, *args, **kwargs) 

Senden Ich habe zwei Fragen

  1. Warum request.data als String kommt statt dict
  2. Wie kann ich die Anfrage aktualisieren?
+0

Bitte geben Sie ein wenig mehr Kontext wie, wie Sie das zusätzliche Attribut hinzufügen und warum Sie die request.data aktualisieren möchten. Beachten Sie, dass das Aktualisieren von request.data normalerweise eine kleine Idee ist. – Linovia

+0

@Linovia Ich möchte das zusätzliche Attribut 'request.data ['age'] = 30' hinzufügen. jetzt kann ich das nicht tun, wie request.data ist string not dict. jetzt, wenn verwenden 'data = json.loads (request.data)' dann 'request.data = json_data' dann bekomme ich Fehler nicht in der Lage, Attribut auf Anfrage zu setzen –

+0

Hinzufügen von" request.data ['age'] = 30 "ist wie Du versuchst etwas zu tun, nicht den Grund, warum Du das tun/brauchen willst. – Linovia

Antwort

2

Es sieht aus wie eine JSON-Zeichenfolge. Um zu wandeln es in einem dict sollten Sie tun:

import json 
data = json.loads(request.data) 

dann können Sie zusätzliche Attribute hinzufügen:

data['age'] = 30 

Dann müssen Sie einen neuen Antrag machen, weil es scheinen, wie Sie kann nicht einfach die alte ändern ein. Dies setzt voraus, dass Sie/Notizen Mitteilung verfassen /:

from rest_framework.test import APIRequestFactory 
factory = APIRequestFactory() 
request = factory.post('/notes/', data, format='json') 
+0

chnage, wenn ich 'request.data = json_data' es heißt nicht in der Lage, Attribut auf Anfrage –

+0

ich habe versuchte das jetzt anzugehen. –

0

nach Ihren Kommentar:

„weil vor der Veröffentlichung Ich brauche die Feldnamen aqs von der API erforderlich ist, um chnage“

Sie sollten stattdessen die Fieldsource argument verwenden.

Dies wird zu konsistenteren Fehlermeldungen führen, da andernfalls der Benutzer mit Feldnamen konfrontiert wird, die er nicht angegeben hat.

0

Wenn Ihr Endpunkt mit einem DRF ViewSet implementiert ist, kann die Lösung darin bestehen, die entsprechende to_internal_value Methode der Serialisierungsklasse zu implementieren und die Daten dort zu ändern.

class MyModelViewSet(viewsets.ModelViewSet): 
    authentication_classes = ... 
    ... 
    serializer_class = MyModelSerializer 


class MyModelSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = MyModel 
     fields = ('id', 'user', ...) 

    def to_internal_value(self, data): 
     instance = super(MyModelSerializer, self).to_internal_value(data) 
     if "lastModified" in data: 
      # instance["id"] = 10 # That's sketchy though 
      instance["user"] = "tom" 
     return instance 
0

Ich habe anders damit umgegangen. Ich überschreiben die CreateAPIView Methode erstellen, wie

class IPAnnotatedObject(CreateAPIView): 
    model = IPAnnotatedObject 
    queryset = IPAnnotatedObject.objects.all() 
    serializer_class = IPAnnotatedObject 
    def create(self, request, *args, **kwargs): 
     request.data['ip_addr'] = self.get_ip() 
     serializer = self.get_serializer(data=request.data) 
     serializer.is_valid(raise_exception=True) 
     ## perform_create calls serializer.save() which calls the serializer's create() method 
     self.perform_create(serializer) 
     headers = self.get_success_headers(serializer.data) 
     return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) 

    def get_ip(self): 
     x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR',None) 
     if x_forwarded_for: 
      ip = x_forwarded_for.split(',')[0] 
     else: 
      ip = self.request.META.get('REMOTE_ADDR',None) 
     return ip 
folgt

Die entsprechende Serializer Klasse sieht wie folgt

class IPAnnotatedObjectSerializer(serializers.ModelSerializer): 
    email = serializers.EmailField(validators=[UniqueValidator(queryset=IPAnnotatedObject.objects.all())]) 
    password = serializers.CharField(write_only=True) 
    ip_addr = serializers.IPAddressField(write_only=True) 
    class Meta: 
     model = IPAnnotatedObject 
     fields = ['email','password','created_ip'] 

    def create(self, validated_data): 
     email, password, created_ip = validated_data['email'], validated_data['password'],validated_data['created_ip'] 
     try: 
      ipAnnoObject = IPAnnotatedObject.objects.create(email=email,password=make_password(password),ip_addr=ip_addr) 
     except Exception as e: 
      # you can think of better error handler 
      pass 
     return ipAnnoOjbect 
1

Ein guter Freund mich nur auf einem viel einfacheren Ansatz zur Schule nahm, als ich oben

illustrieren
class CreateSomething(CreateAPIView): 
    model = Something 
    queryset = Something.objects.all() 
    serializer_class = SomethingSerializer 

    perform_create(self,serializer): 
    def perform_create(self,serializer): 
     ip = self.get_ip() 
     ## magic here: add kwargs for extra fields to write to db 
     serializer.save(ip_addr=ip) 

    def get_ip(self): 
     x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR',None) 
     if x_forwarded_for: 
      ip = x_forwarded_for.split(',')[0] 
     else: 
      ip = self.request.META.get('REMOTE_ADDR',None) 
     return ip 

class SomethingSerializer(serializers.ModelSerializer): 
    email = serializers.EmailField(validators=[UniqueValidator(queryset=Something.objects.all())]) 
    fieldA = serializers.CharField() 
    fieldB = serializers.CharField() 

    class Meta: 
     model = Customer2 
     fields = ['email','fieldA','fieldB','ip_addr'] 
     read_only_fields = ['ip_addr'] 
Verwandte Themen