How to serialize JSON Request data from serializer in Django? - python

I am trying to serialize a json data through serializers.Serializer
{
"data": {
"phoneNumber": "1234567890",
"countryCode": "+11",
"otp": "73146",
}
}
The sterilizer class I wrote for it
class VerifyOtpSerializer(serializers.Serializer):
phone_number = serializers.CharField(max_length=225, source='phoneNumber', required=True)
country_code = serializers.CharField(max_length=225, source='countryCode', required=True)
otp = serializers.CharField(max_length=255, required=True)
and also
I don't know why source is not working, I tried the JSON in the picture below but still it's saying the field is required

source value is what the passed value's key will be changed into. So source value is expected to be on your Model.
The name of the attribute that will be used to populate the field.
What you really want is something that changes camel case payload into a snake case. Just use djangorestframework-camel-case and remove source from your serializer fields.

Your keys are wrong in the request. as Tom said the source should be an attribute of the model object. so you have to match keys in request and serializer
change phoneNumber > phone_number
change countryCode > country_code

The response object you are are sending to your serializer is in correct. The key of your request object should be exactly what you have defined in your serializer.
Try sending this to your serializer.
{
"data" : {
"phone_number":"1234567890",
"country_code":"+11",
"otp":"73146"
}
}

Related

flask restex #expect with nested fields

I am using nested fields to validate an incoming post request using #api.expect like
payload1 = api.model('Payload', {
'prop1': fields.Nested({'prop1_inner' : fields.String(required=True)})
})
payload2 = api.model('Payload', {
'prop1': fields.Nested(api.model("metadata", {
'prop1_inner': fields.String(required=True)
}))
})
#doesn't work
#api.expect(payload1 , validate=True)
def post(self):
#works
#api.expect(payload2 , validate=True)
def post(self):
I am getting an exception when I use payload1 like
'dict' object has no attribute 'name'
I expect both forms to validate the incoming request. Would like to know the reason nested fields without model wrapper doesn't work.
Consider this.
Nested models are not usually defined inside. They have to be a discrete model themselves with a discrete name, As swagger documents nested fields as separate models and so, here,
payload1_addon = api.Model('PayloadAddon',{
'prop1_inner' :fields.String(required=True)})
payload1 = api.model('Payload', {'prop1': fields.Nested(payload1_addon)})

In Django-Rest-Framework POST call which updates manytomany field works with JSON but not with form-data

I want to run a POST call that creates a "group". Assume that "persons" will all be existent. Even if they aren't, an error is not a problem.
class Group(models.Model):
title = models.CharField(max_length=70)
persons = models.ManyToManyField(to=Person, blank=True)
file = models.FileField(upload_to=file_location, null=True, blank=True)
class GroupSerializer(serializers.ModelSerializer):
persons = serializers.PrimaryKeyRelatedField(many=True, queryset=Person.objects.all())
class Meta:
model = Group
fields = '__all__'
If I send a JSON like
{
"title": "Drama Club",
"persons": [1,2,3]
}
it will work. But since I cannot upload a file, I use FORM-DATA.
title: Drama Club
persons: [1,2,3]
file: <whatever the format is>
Now here comes the problem. IT DOES NOT WORK. It returns this error
{
"persons": [
"Incorrect type. Expected pk value, received str."
]
}
Even if I remove everything else, and just send persons: [1,2,3] as form-data, it returns the same error.
I really cannot understand this behavior. (I am using POSTMAN to check this)
It turns out that form-data does not take an array. So, instead of
persons : [1,2,3]
I will have to send
persons : 1
persons : 2
persons : 3
Django-rest-framework will do the rest.
Putting this answer here, because it took me a very long time to figure it out.
(if there is a way to send an array in form-data, without special parsing on the backend, I would love to know)
If you want to upload a file and send the JSON payload as well, take a look at DRF MultipartParser

Return custom JSON response from ListAPIView Django 3.0 Rest Framework

I have created an API using DRF That is able to list and view particular records based on the URL pattern specified. For example:
for the request:
curl -v http://127.0.0.1:8000/get_details/120001/
I am able to get a response:
[
{
"subject": "Data Structures",
"course": "CSE"
},
{
"subject": "Thermodynamics",
"course": "Chemistry"
},
{
"subject": "Organic Chemistry",
"course": "Chemistry"
},
{
"subject": "Optics",
"course": "Physics"
}
]
Where '120001' is the user_id the database is searched against.
But the I want the response in the following format:
{'Chemistry': ['Thermodynamics', 'Organic Chemistry'], 'CSE': ['Data Structures'], 'Physics': ['Optics']}
(content wise, I am not considering indentation and other factors)
While I am able to write code for the logic of how to create and populate this dictionary, I am unable to figure out how to return this as response and from where.
I am using generics.ListAPIView as the view class.
Here is my model (models.py):
class Subject(models.Model):
user_id = models.CharField(null = False, max_length=10)
subject = models.CharField(max_length=50)
course = models.CharField(max_length=50)
def __str__(self):
return self.subject
Serializer (serializers.py):
class SubjectSerializer(serializers.ModelSerializer):
class Meta:
model = Subject
fields = ['subject', 'course']
and, views.py (for the first output in default format):
class SubjectView(generics.ListAPIView):
serializer_class = SubjectSerializer
def get_queryset(self):
username = self.kwargs['user_id']
return Subject.objects.filter(user_id = username).only('subject','course')
I have written a logic to create the dictionary to send as response (as described in my desired output) by extracting values using Subject.objects.values(....) and then looping through the results to create my dictionary but I just don't get where (that is, which function) to write it in and return from.
Is there any function provided by the generics.ListAPIView class that can allow me to do this? And if not, then what other alternative approach can I try?
I am an absolute beginner at Django and any help will be appreciated. Also, it will be of great help if anyone can suggest me a practical guide/tutorial/playlist from where I can learn DRF through code examples to speed up my learning process.
Thank you!
You need to override to_representation method of Serializer
from docs
There are some cases where you need to provide extra context to the
serializer in addition to the object being serialized.
class SubjectSerializer(serializers.ModelSerializer):
class Meta:
model = Subject
fields = ['subject', 'course']
def to_representation(self, instance):
data = super(SubjectSerializer, self).to_representation(instance)
# manipulate data here
return data

Django Rest Framework: Overwriting validation error keys

When translating my site to another language a problem occurred.
I want to handle Validation Errors properly and allow my front-end friends to display them well.
Is there a way to overwrite keys in response message of DRF when Validation Error happend?
What do I mean by that - I want to change this:
{
"name": ["This field is required."]
}
into:
{
"username": ["This field is required."]
}
Is there a way to do that without writing each and every one of validators?
You can change the name field in the ModelSerializer to username.
example:
class CustomSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='name')
class Meta:
model = ...
fields = ('username', ...)
Now in validation errors it will have the key username instead.

Django Doesn't Serialize id of the model

I have a simple class :
class Item(models.Model):
name = models.CharField(max_length=250)
I need to serialize it to JSON with the ID as part of the JSON, but the ID never gets serialized when called in the view:
items_json = serializers.serialize('json', item_list)
The item_list json as received by the browser contains only name, not the ID.
I need the ID for the processing on the client side which returns to the server later.
1) I'd like to avoid creating another ID if possible
2) I haven't created a Serializer Class. I am not sure where and how to do that.
I found the solution. The pk field that is sent over is the id. The id will now show up in the fields. So in javascript you should do:
$.each( $.parseJSON(data), function(key, val) {
console.log("ID: " + val.pk)
});

Categories

Resources