How can modify request.data in django REST framework
Solution 1
In case your API is APIView
then you should use update function to expand your request data object without losing the data sent from the client-side.
request.data.update({"id": "10", "user": "tom"})
Solution 2
request.data
should be an immutable QueryDict
, rather than a string. If you need to modify it:
if isinstance(request.data, QueryDict): # optional
request.data._mutable = True
request.data['age'] = "30"
The only reason you might check if it's an instance of QueryDict
is so it's easier to unit test with a regular dict
.
Solution 3
A good friend just took me to school on a much simpler approach than I illustrate above
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']
Solution 4
Generally request
in drf views is rest_framework.request.Request
instance. Following to it's source code (djangorestframework==3.8.2
):
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
You can do:
request._full_data = your_data
Solution 5
It looks like a json string. To convert it to a dict you should do:
import json
data = json.loads(request.data)
then you can add extra attributes:
data['age'] = 30
Then you will have to make a new request because it seem like you cant just change the old one. This assumes that you are posting to /notes/:
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.post('/notes/', data, format='json')
John Kaff
Updated on January 16, 2022Comments
-
John Kaff over 2 years
I am using Django REST Framework
request.data = '{"id": "10", "user": "tom"}'
I want to add extra attribute like
"age": "30"
before sending it to further likerequest.data = new_data response = super().post(request, *args, **kwargs)
I have two issues
- Why request.data is coming as string rather than dict
- How can i update the request.data
-
John Kaff over 8 yearsif i use
request.data = json_data
it says not able to set attribute on request -
Alec Gerona over 5 yearsIt's so sad that there isn't a more intuitive way to do this. Probably a better mixin or some predefined function.
-
Csaba Toth over 5 yearsBTW, you can also make some manipulations if you override the
ModelViewSet
'screate
andupdate
methods. -
JTW over 5 yearsYikes... although this works, DRF should have a cleaner way to accomplish this.
-
emanuel sanga almost 3 yearsThe best way to alter in a generic view is to override get_serializer method... This is a bit redundant as your serializer is not working at all if you are helpin it create
-
emanuel sanga almost 3 years@Altus, there are ways to do that, or you mean djangoish ways?
-
validname over 2 yearsFYI accessing private methods or attributes is a really bad idea, but if you've got no other options you "can" do that.
-
isifzade about 2 yearswhere "to_internal_value" method called?
-
Csaba Toth about 2 years@isifzade it is called by the DRF framework as part of the deserialization workflow of the object. See related stackoverflow.com/questions/34196331/… and django-rest-framework.org/api-guide/fields
-
Alexander P almost 2 yearsAttributeError: This QueryDict instance is immutable