Convert model objects in OrderedDict to Json django - json

In [32]: obj
OrderedDict([('code', 'COO21'),
('name', 'sai'),
('country', <Country: INDIA>)])
Error:-
TypeError: Object of type Country is not JSON serializable
Not able to convert model objects in ordered dict to json

Override the to_representation() method in your serializer to customize the response when sending back to the view/controller.
instance is the object of the serializing model.
def to_representation(self, instance):
ret = super().to_representation(instance)
ret["country"] = instance.country.name if country else None
return ret

Related

Serializing Django FilterSet

I'm using django-filter (https://django-filter.readthedocs.io/en/stable/guide/install.html).
How can I serialize the Filterset in order to send it back to my angular Frontend?
views.py:
#api_view(['GET'])
def materialien_search(request):
filter = MaterialFilter(request.GET, queryset=Materialien.objects.all())
materialien_serializer = MaterialienSerializer(filter, many=True)
return JsonResponse(materialien_serializer.data, safe=False)
serializers.py:
class MaterialienSerializer(serializers.ModelSerializer):
class Meta:
model = Materialien
fields = [field.name for field in Materialien._meta.get_fields()]
filter.py:
class MaterialFilter(django_filters.FilterSet):
class Meta:
model = Materialien
fields = '__all__'
I'd be thankful for every help.
The Filterset should be a GET QueryDict, but all my attemps of serializing or converting it to JSON failed because Materialfilter is neither iterable nor serializable. So json.dumps and json.load and
serializers.serialize("json", filter) did not work.
TypeError: 'MaterialFilter' object is not iterable
TypeError: Object of type MaterialFilter is not JSON serializable

Return serialized JSON from DRF Serializer

I have a custom serializer that is returning a string representation of JSON. This serializer uses django.contrib.gis.serializers.geojson.Serializer which is much faster than the DRF serializer. The downside of this serializer is that it returns everything already serialized into a string, rather than as a JSON serializiable object.
Is there a way to shortcut the DRF obj>json string process and just pass the string as the json response?
Currently I am doing the following, but the obj>string>dict>string process is not ideal:
from django.contrib.gis.serializers.geojson import Serializer
from json import loads
class GeoJSONFastSerializer(Serializer):
def __init__(self, *args, **kwargs):
self.instances = args[0]
super().__init__()
#property
def data(self):
# The use of json.loads here to deserialize the string,
# only for it to be reserialized by DRF is inefficient.
return loads(self.serialize(self.instances))
Which is implemented (simplified version) in the view:
from rest_framework.mixins import ListModelMixin
from rest_framework.viewsets import GenericViewSet
class GeoJSONPlaceViewSet(ListModelMixin, GenericViewSet):
serializer_class = GeoJSONFastSerializer
queryset = Places.objects.all()
I think that you could define a custom renderer and just pass the data, something like this,
from django.utils.encoding import smart_unicode
from rest_framework import renderers
class AlreadyJSONRenderer(renderers.BaseRenderer):
media_type = 'application/json'
format = 'json'
def render(self, data, media_type=None, renderer_context=None):
return data
and in the view just add
renderer_classes = [AlreadyJSONRenderer]

Object of type 'Mycart' is not JSON serializable in Django

I want to add dictionary(having models) datatype object to request.session
but getting "Object of type 'Mycart' is not JSON serializable in Django"
product_details = {}
for product in products_in_cart:
product_details.update({product.id:
(product,request.POST['quantity'+str(product.product.id)])})
request.session['product_details'] = product_details
I expect the dictionary updated in session but the actual output is "Object of type 'Mycart' is not JSON serializable in Django"
The problem is with the product which is the first parameter of your tuple inside of your dictionary. you need to serialize it before you can use it in your tuple like this:
from django.core import serializers
product_details = {}
for product in products_in_cart:
s_product = serializers.serialize("json", [product])
product_details.update({product.id:
(s_product,request.POST['quantity'+str(product.id)])})
request.session['product_details'] = product_details

serialize data to ArrayField(models.IntegerField(),default=list) field

I have the following field in postgres database :ArrayField(models.IntegerField(),default=list).
When I send data from post request I get the following error:
invalid literal for int() with base 10: '[176,68]'
while the data sent is price:[176,68]
Here is my serializer for price :
class StringArrayField(ListField):
"""
String representation of an array field.
"""
def to_representation(self, obj):
obj = super().to_representation( obj)
# convert list to string
return ",".join([(element) for element in obj])
def to_internal_value(self, data):
return super().to_internal_value( data)
class MySerializer(serializers.ModelSerializer):
price = StringArrayField()
class Meta:
model = myModel
fields =('price')
You must pass a child serializer to the listfield.
price = serializers.ListField(
child=serializers.IntegerField(min_value=0, max_value=100)
)

django rest framework - request context key error

I have two models (Like and News). I am using django-rest-framework to make a web api out of it.
class Like(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class News(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=150)
...
likes = GenericRelation(Like)
A Like object has its own user field to store who liked the News object. Now to check if a specific user exists in any of the likes of a News object, I am getting request.user from a SerializerMethodField.
class NewsSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
likes_count = serializers.IntegerField(source='likes.count', read_only=True)
user_in_likes = serializers.SerializerMethodField()
class Meta:
model = News
fields = ('user', 'title', 'body', 'article_image', 'pub_date', 'likes_count', 'user_in_likes')
def get_user_in_likes(self, obj):
user = self.context['request'].user
what = obj.likes.filter(user=user).exists()
return what
When I go the /news/ url, I get the json objects including the user_in_likes to true/false for each news object.
However, I have another serialzer for different model which imports NewsSerializer class and other similar serializers:
class ActivityObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
if isinstance(value, User):
serializer = UserSerializer(value)
elif isinstance(value, Job):
serializer = JobSerializer(value)
elif isinstance(value, News):
serializer = NewsSerializer(value)
elif isinstance(value, Tender):
serializer = TenderSerializer(value)
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
class ActivitySerializer(serializers.HyperlinkedModelSerializer):
actor = ActivityObjectRelatedField(read_only=True)
target = ActivityObjectRelatedField(read_only=True)
class Meta:
model = Activity
fields = ('url', 'actor', 'verb', 'target', 'pub_date')
Now if I visit /activities/, to get the activities objects I am getting an error:
KeyError at /activities/
'request'
And it points to the line of SerializerMethod of NewsSerialize class where self.context['request'].user is used.
Exception Location: /vagrant/myproject/news/serializers.py in get_user_in_likes, line 25
Again if I visit /news/ url, everything is fine and I get news objects. What am I missing here? Why is request not being recognized in the ActivitiesSerializer class? Please help me solve this problem. Thank you.
You are getting this error because you are not passing request in the context when instantiating the NewsSerializer class or other similar serializers in the to_representation() method.
You are manually instantiating the particular serializer class in to_representation() method. So, after instantiation, that particular serializer does not have access to ActivitySerializer's context thereby leading to the error.
You can pass the ActivitySerializer's context during instantiation of the relevant serializer in the to_representation() method.
class ActivityObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
if isinstance(value, User):
serializer = UserSerializer(value, context=self.context) # pass context
elif isinstance(value, Job):
serializer = JobSerializer(value, context=self.context) # pass context
elif isinstance(value, News):
serializer = NewsSerializer(value, context=self.context) # pass context
elif isinstance(value, Tender):
serializer = TenderSerializer(value, context=self.context) # pass context
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
It seems like you don't populate the context dictionary of NewsSerializer with your request in the /activities/ view.
You probably use a class based view provided by Django REST Framework which populates this dictionary for you (see the get_serializer_context() method) and passes it to the Serializer instance. That's why it's automatically available to your serializer in your /news/ view.
In your /activities/ view, though, the context is passed to ActivitySerializer and isn't (automatically) propagated further from there. That's why there's no request key in your context dictionary of NewsSerializer. You would need to pass your request object to the NewsSerializer instance. To pass extra context to a Serializer you can add a context parameter containing a dictionary when instantiating (see the DRF documentation).