19👍
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"})
16👍
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
.
- [Django]-Django: Hide button in template, if user is not super-user
- [Django]-Django orm get latest for each group
- [Django]-How to deploy an HTTPS-only site, with Django/nginx?
8👍
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']
- [Django]-ImproperlyConfigured: You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings
- [Django]-Django Reverse Accessor Clashes
- [Django]-Django: signal when user logs in?
8👍
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
- [Django]-What is choice_set in this Django app tutorial?
- [Django]-"No installed app with label 'admin'" running Django migration. The app is installed correctly
- [Django]-Django Admin linking to related objects
3👍
If your endpoint is implemented with a DRF (Django REST Framework) ViewSet
the solution can be to implement the corresponding serializer class’s to_internal_value
method and modify the data there.
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
- [Django]-How to get primary keys of objects created using django bulk_create
- [Django]-Django Local Settings
- [Django]-Adding a user to a group in django
2👍
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')
- [Django]-Django model fields validation
- [Django]-What is pip install -q -e . for in this Travis-CI build tutorial?
- [Django]-Database returned an invalid value in QuerySet.dates()
2👍
If you are afraid of altering your request object, then use deep copy to copy the object and then you can easily alter it.
Usage::
from copy import deepcopy
# here is your other code and stuffs
data = deepcopy(request.data)
feel free to alter the data as you want as it is now mutable.
So far, this is my preferred way of altering if not using a generic view.
For any drawbacks of this method, please comment below!
- [Django]-Django's SuspiciousOperation Invalid HTTP_HOST header
- [Django]-Django : Testing if the page has redirected to the desired url
- [Django]-Favorite Django Tips & Features?
1👍
Though other answers are good but i just wanted to add one thing here;
We have now two ways to update a request.data
object But before that, check if it is a QueryDict (as already mentioned by @mikebridge);
from django.http.request import QueryDict
if isInstance(request.data, QueryDict):
request.data._mutable = True
After that, to update the request.data, first way is;
request.data.update({'key': 'new_value'})
this will work fine, but say if the request.data[‘key’] which you want to update is a list, then the value will not get changed completely by the new_value
but it will get appended to the older list which may cause trouble and you may not get the desired result.
So to overcome that, i.e, to completely change the value of some key, use the second method;
request.data['key'] = 'new_value'
This will change the value of request.data['key']
completely to new_value
.
- [Django]-Django rest framework change primary key to use a unqiue field
- [Django]-Django QuerySet order
- [Django]-Using the reserved word "class" as field name in Django and Django REST Framework
0👍
According to your comment:
“because before posting i need to chnage the field names aqs required by the API”
You should be using the Field
‘s source
argument instead.
This will make error messages more consistent otherwise your user will face errors with field names they didn’t provide.
- [Django]-How to show a PDF file in a Django view?
- [Django]-How to get an ImageField URL within a template?
- [Django]-How to rename items in values() in Django?
0👍
I have dealt with this differently. I override the CreateAPIView create method, as follows
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
The corresponding serializer class looks like follows
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
- [Django]-Unable to import path from django.urls
- [Django]-Django 1.8: Create initial migrations for existing schema
- [Django]-Django syncdb and an updated model
0👍
I did the following:
import json
data = json.dumps(request.data)
data = json.loads(data)
data['age'] = 100
now use variable data
instead of request.data
.
- [Django]-Django reverse lookup of foreign keys
- [Django]-Django select_for_update cannot be used outside of a transaction
- [Django]-Error: "dictionary update sequence element #0 has length 1; 2 is required" on Django 1.4
0👍
May be override is_valid
in your serializer class will be more readable
class YourSerializer
# Don't forget it
age = serializers.IntegerField()
def is_valid(self, raise_exception: bool = ...) -> bool:
self.initial_data["age"] = 30
return super().is_valid(raise_exception)
- [Django]-South migration: "database backend does not accept 0 as a value for AutoField" (mysql)
- [Django]-Circular dependency in Django Rest Framework serializers
- [Django]-Running ./manage.py migrate during Heroku deployment