Serializing nested object to string in Django Rest Framework - python

I am trying to connect my Django application to the mailchimps API with help from the Django Rest Framework, if I want to create a batch operation, I need to send the following call:
{
"operations": [
{
"method": "PUT",
"path": "lists/abc123/members/817f1571000f0b843c2b8a6982813db2",
"body": "{\"email_address\":\"hall#hallandoates.com\", \"status_if_new\":\"subscribed\"}"
},...
]
}
As you can see, the body object should be a json string. To create these calls, I created a model operation:
models.py
class Operation(object):
def __init__(self, method, list, contact):
email_clean = contact.email_address.lower().encode('utf-8')
subscriber_hash = hashlib.md5(email_clean).hexdigest()
serializer = ContactSerializer(contact)
body = serializer.data
self.method = method
self.path = "lists/%s/members/%s" % (list, subscriber_hash)
self.body = body
And the following serializer:
serializer.py
class OperationSerializer(serializers.Serializer):
method = serializers.CharField()
path = serializers.CharField()
body = serializers.CharField(allow_blank=True, required=False)
When I use my serializer to generate JSON, and parse the data with JSONRenderer(), the following call is returned:
{
"operations": [
{
"method": "PUT",
"path": "lists/abc123/members/817f1571000f0b843c2b8a6982813db2",
"body": "{\'email_address\':\'hall#hallandoates.com\', \'status_if_new\':\'subscribed\'}"
},...
]
}
This call breaks because of the single quotes, can anyone help me a hand in solving this?

Related

django rest framework returning list instead of dict after serializering data

I am returning some data but instead of dict I am getting list in return
my serializer.py file
class CommitteeDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = Committee
fields = ['id','com_name', 'com_members_limit', 'com_amount_per_month',
'com_starting_date', 'com_join_id', 'com_status']
my views.py
serializer = CommitteeDetailsSerializer(get_committee, many=True)
I am getting this data list
{
"status": "success",
"msg": "Done.",
"data": [
{
"id": 19,
"com_name": "My second Committee",
"com_members_limit": 4,
"com_amount_per_month": 1000,
"com_starting_date": "2022-05-04",
"com_join_id": "GR9PKKOX65",
"com_status": "pending"
}
]
}
what I want is dict here in data {}
In your views.py in the serializer you passed many=True, hence its returning a list. Remove that and you should get one single object serialized instead of a list.

How to get list of related objects in Django-rest-Framework

I am trying to implement Nested serializer for the first time in django-rest-framework
My requirement is i need the response data in below form :-
{
id: 0,
title: "Fresh",
data: [
[{
image: ".../assets/images/banana.jpeg",
name: "Fruits",
image_scaling: 2,
API: "http://database_api"
},
{
image: "../assets/images/banana.jpeg",
name: "Vegetables",
image_scaling: 2,
API: "http://database_api"
},
{
image: "../assets/images/banana.jpeg",
name: "Exotic Vegetables",
image_scaling: 2,
API: "http://database_api"
}
]
]
}
I am validating the token for the get api and listing the objects form DB.
My current implementation of views.py is :-
class home(APIView):
def get(self,request,format=None):
header_token = request.META.get('HTTP_AUTHORIZATION', None)
if header_token is not None:
token = header_token
access_token=token.split(' ')[1]
print(access_token)
if(validate_token(access_token) == None):
raise NotFound('user does exist')
queryset=Fresh.objects.all().select_related('data')
print(queryset)
serializer = FreshSerializer(queryset,many=True)
return Response(serializer.data)
Serializer.py is :-
class DataSerializer(serializers.ModelSerializer):
class Meta:
model=data
fields = ('name','image_scaling','image')
class FreshSerializer(serializers.ModelSerializer):
data=DataSerializer(read_only=True, many=False)
class Meta:
model = Fresh
fields = ('title','data')
models.py is :-
class data(models.Model):
name=models.CharField(max_length=9,null=True)
image_scaling=models.IntegerField(default=0,null=True)
image=models.URLField(max_length = 200)
def __str__(self):
return str(self.name)
class Fresh(models.Model):
title=models.CharField(max_length=9)
data=models.ForeignKey(data,on_delete=models.CASCADE,default=None, null=True)
def __str__(self):
return str(self.title)+" " +str(self.data)
My current output is :-
[
{
"title": "vegetable",
"data": {
"name": "vegetable",
"image_scaling": 2,
"image": "https......jpg"
}
},
{
"title": "exoticveg",
"data": {
"name": "exoticveg",
"image_scaling": 2,
"image": "https://.......jpg"
}
} ]
I was trying to do by listapiview and modelviewset, but i am not able to get the desired output.I have seen similar queries in stack-overflow, but no solution seems to work for me. I am not getting list of objects of foreign key , am i doing something wrong in my model or running wrong query? I am really stuck at it.
How shall i go about it.
Please help!!!

Django - How to map object from another API and send in GET response

I would like to map object from another API and send in GET response. I'm going to change only id of received object. Let's assume I get data from another API in such format:
{
"id": "31242",
"name": "sth1",
"price": "44",
"data": "2017-06-07",
}
In my database I have table object1 with values:
{
"id": "123",
"name": "sth1",
},
{
"id": "124",
"name": "sth2",
},
{
"id": "125",
"name": "sth3",
}
Field name is unique both in data from API and in data from database. I receive an object named sth1. So now I would like to find it in my database and get his id, replace with id from API and send GET response. In this case my response would look in this way:
{
"id": "123",
"name": "sth1",
"price": "44",
"data": "2017-06-07",
}
At this moment this is my URL - url(r'^data/(?P<name>\w+)$', views.DataList),
but I would like to have such URL - localhost:8000/data?name=sth
Myview.py:
#api_view(['GET'])
def DataList(request, name=None):
if request.method == 'GET':
quote = getDataFromAPI().get(name)
return Response(quote)
serializers.py:
class Object1Serializer(serializers.ModelSerializer):
class Meta:
model = Object1
depth = 1
fields = '__all__'
models.py:
class Object1(models.Model):
name = models.CharField(max_length=200)
I have done it in this way:
#api_view(['GET'])
def DataList(request):
t = request.GET.get("t","")
quote = getDataFromAPI().get(t)
id = Object1.objects.get(t=t)
quote["id"] = id
return Response(quote)
But I get error:
TypeError: Object of type 'Object1' is not JSON serializable
I suppose, your view should look somewhat like this,
#api_view(['GET'])
def DataList(request):
t = request.GET.get("t","")
quote = getDataFromAPI().get(t)
id = Object1.objects.get(t=t).id #put the id of the object in the variable.
#not the object itself.
quote["id"] = id
return Response(quote)
If you want to change the url from
url(r'^data/(?P<name>\w+)$', views.DataList) to localhost:8000/data?name=sth you'd need to change your api endpoint from
#api_view(['GET'])
def DataList(request, name=None):
to
#api_view(['GET'])
def DataList(request):
name = request.GET.get("name","")
and then take the id of object from your database by querying
id = Object1.objects.get(name=name)
and then updating id in response to be sent
quote["id"] = id

Serialize a string without changes in Django Rest Framework?

I'm using Python's json.dumps() to convert an array to a string and then store it in a Django Model. I'm trying to figure out how I can get Django's REST framework to ignore this field and send it 'as is' without serializing it a second time.
For example, if the model looks like this(Both fields are CharFields):
name = "E:\"
path_with_ids= "[{"name": "E:\", "id": 525}]"
I want the REST framework to ignore 'path_with_ids' when serializing so the JSON output will look like this:
{ "name": "E:\", "path_with_ids":
[ {"name": "E:\", "id": 525} ] }
and not like this:
{
"name": "E:\",
"path_with_ids": "[{\"name\": \"E:\\\", \"id\": 525}]" }
I've tried to make another serializer class that spits out the input it gets 'as is' without success:
Serializers.py:
class PathWithIds(serializers.CharField):
def to_representation(self, value):
return value.path_with_ids
class FolderSerializer(serializers.ModelSerializer):
field_to_ignore = PathWithIds(source='path_with_ids')
class Meta:
model = Folder
fields = ['id', 'field_to_ignore']
Please help!
I ended up using a wasteful and sickening method of deserializing the array before serializing it again with the REST framework:
Serializers.py:
import json
class PathWithIds(serializers.CharField):
def to_representation(self, value):
x = json.loads(value)
return x
class FolderSerializer(serializers.ModelSerializer):
array_output = PathWithIds(source='field_to_ignore')
class Meta:
model = Folder
fields = ['id', 'array_output']
Output in the rest API:
{
"name": "E:\",
"array_output": [
{
"name": "E:\",
"id": 525
}
] }

How to access ForeignKey data without making extra queries in Wagtail(django)

I have the following two classes in my app.models and i'm using the wagtail APIs to get the data as json
class AuthorMeta(Page):
author=models.OneToOneField(User)
city = models.ForeignKey('Cities', related_name='related_author')
class Cities(Page):
name = models.CharField(max_length=30)
So, when I try /api/v1/pages/?type=dashboard.AuthorMeta&fields=title,city, it returns the following data:
{
"meta": {
"total_count": 1
},
"pages": [
{
"id": 11,
"meta": {
"type": "dashboard.AuthorMeta",
"detail_url": "http://localhost:8000/api/v1/pages/11/"
},
"title": "Suneet Choudhary",
"city": {
"id": 10,
"meta": {
"type": "dashboard.Cities",
"detail_url": "http://localhost:8000/api/v1/pages/10/"
}
}
}
]
}
In the city field, it returns the id and meta of the city. How can I get the name of the city in the response here, without making an extra query? :/
I couldn't find any solution in the Documentation. Am I missing something?
Use Django model property to return through the ForeignKey:
class AuthorMeta(Page):
author=models.OneToOneField(User)
city = models.ForeignKey('Cities', related_name='related_author')
city_name = property(get_city_name)
def get_city_name(self):
return self.city.name
Check Term Property to better understand the concept
In case you have the foreign key in a Streamfield, e.g. a PageChooserBlock, you can customize the api response by overwriting the get_api_representation of a block, as described in the example as provided here:
class CustomPageChooserBlock(blocks.PageChooserBlock):
""" Customize the api response. """
def get_api_representation(self, value, context=None):
""" Return the url path instead of the id. """
return value.url_path

Categories

Resources