Serializing Django FilterSet - django-filter

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

Related

Convert model objects in OrderedDict to Json django

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

DJANGO ListView returns HTTPResponse, but I need a json

I am having a problem around the Class Based Views in Django. I need to create JSON responses, instead of rendering to a template.
class AllItem(ListView):
model = MyModel
context_object_name = 'items'
template_name = 'mymodel/index.html'
I also have a serializer class
class SpendingConfigSerializer(serializers.ModelSerialier):
class Meta:
model = SpendingConfig
fields = ('record_date', 'amount', 'name')
Does anyone know how to connect them?
Thanks
Z.
You can make use of a ListAPIView and specify your SpendingConfigSerializer as serializer:
from rest_framework import generics
class UserList(generics.ListCreateAPIView):
queryset = SpendingConfig.objects.all()
serializer_class = SpendingConfigSerializer

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]

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).