Django serializer for one object - python

I'm trying to figure out a way to serialize some Django model object to JSON format, something like:
j = Job.objects.get(pk=1)
##############################################
#a way to get the JSON for that j variable???
##############################################
I don't want:
from django.core import serializers
serializers.serialize('json', Job.objects.get(pk=1),ensure_ascii=False)
Because it returns JSON array, not a single object representation.
Any ideas?
One way I'm thinking of: is to find a way to get a hash(attribute,value) of the object and then use simplejson to get the JSON representation of it, however I don't know how to get that hash.

How about just massaging what you get back from serializers.serialize? It is not that hard to trim off the square brackets from the front and back of the result.
job = Job.objects.get(pk=1)
array_result = serializers.serialize('json', [job], ensure_ascii=False)
just_object_result = array_result[1:-1]
Not a fancy answer but it will give you just the object in json notation.

Method-1
Use Django Serializer with python format
from django.core import serializers
j = Job.objects.get(pk=1)
response = serializers.serialize('python', [j], ensure_ascii=False)
Method-2
use json format while serializing and loads the string response
import json
from django.core import serializers
j = Job.objects.get(pk=1)
json_str_response = serializers.serialize('json', [j], ensure_ascii=False)
response = json.loads(json_str_response)[0]
Method-3
Use Django REST Framework's Serializer class
define a serializer class and serialize the instance as
from rest_framework import serializers
class JobSerializer(serializers.ModelSerializer):
class Meta:
model = Job
fields = '__all__'
j = Job.objects.get(pk=1)
response = JobSerializer(instance=j).data
Reference
1. Serializer Django model object

I would suggest using Django's model_to_dict. If I'm not mistaken, serializers.serialize() relies on it, too, but it only works for list, not single model instance. That's how you get a dict instance with your model fields out of a single model:
from django.forms.models import model_to_dict
# assuming obj is your model instance
dict_obj = model_to_dict( obj )
You now just need one straight json.dumps call:
import json
json.dumps(dict_obj)

Related

Serialize custom data in DRF

I have two types of static data and don't need any models because I don't want to save those data in the database. The data are generated from a class RandomObjectGenerator.
Data 1 is a string whose length could be up to 2,097,152
Date 2 is a JSON data whose size could be up to 4 like {'a':1, 'b':2, 'c':3, 'd':4}
views.py
from django.shortcuts import render
from rest_framework import views
from rest_framework.response import Response
from .generate import RandomObjectGenerator
from .serializers import ObjectSerializers
import json
# Create your views here.
class ApiView(views.APIView):
def get(self, request):
randomObject=RandomObjectGenerator().get_random_objects()
randomObjectCount=RandomObjectGenerator().get_random_object_count()
objectSerialize=ObjectSerializers(data={'randData':randomObject,'randCount': json.dumps(randomObjectCount)})
if objectSerialize.is_valid():
objectSerialize.save()
return Response(objectSerialize.data)
else:
return Response(objectSerialize.errors)
serializers.py
from rest_framework import serializers
class ObjectSerializers(serializers.Serializer):
randData=serializers.CharField()
randCount=serializers.IntegerField()
I am getting two types of errors here. If I use serializers.IntegerField() then I am getting the "A valid integer is required." error then if I try to use serializers.CharField() then it's showing create() must be implemented.
I got stuck for while and couldn't get any idea how i fixed it.
create() need to be implemented on any serializer you call .save() because calling create is what save does.
So the question really is, why are you calling .save() if you have no intention of saving this to a database? what are you conceptually saving here?
Removing the row with save() from the view should solve your issue.

Django, transform from a queryset to json and use a value from a key

This is my model.py
class Ont_Pruebas_Json(models.Model):
usuario_id = models.CharField(max_length=12)
data = jsonfield.JSONField()
def __str__(self):
return '{}'.format(self.usuario_id)
On data field I am storing this:
{u'1': {u'user': u'user1',u'mac': u"'00:00:00:00:00:01'"}, u'2': {u'user': u'user1',u'mac': u"'00:00:00:00:00:01'"}}
On my views.py
I am passing the query set this way:
context['context_json'] = Ont_Pruebas_Json.objects.all()
How can pass from the queryset to json format so I can choose for example from 1 the key mac and get the value: 00:00:00:00:00:01.
In general, you shouldn't store json data directly in the database. There are lots of potential problems doing this. For example, if data is missing you might not know because you didn't validate it.
You should first parse your data so that python can read it. If you are using Django Rest Framework(DRF) use a serializer.
However, I found serializers confusing at the start so if you want to parse a queryset do so do as shown below.
from .models import Ont_Pruebas_Json
import json
query = Ont_Pruebas_Json.objects.get(usuario_id ='some_user_id')
data = json.loads(str(query))

Django-Rest-Framework APIView returning a model object and an image

suppose that I want to return in a APIView.get a (non model) object conatining 2 properties, one of them is a model object, and the other is a binary Image
I've tried several ways and had problems with serializer.
thanks!
Serializer:
class MyCustomSerializer(serializers.ModelSerializer):
class Meta:
model = MyCustom
fields = '__all__'
View:
class MyCustomGet(APIView):
def get(self, request, format=None):
serializer = MyCustomSerializer
obj = s.get_custom()
return Response({"obj": serializer(obj.obj).data, "image": obj.image})
get_custom:
class CustomClass:
obj = None
image = None
def get_custom():
r = CustomClass()
r.obj = MyCustom.objects.all().first()
r.image = PIL.Image.open('file/path.png')
return r
You are trying to render an image (binary data) in a JSON response (string). This would not work. If you want to pass the image in a JSON string, you have to encode it as a string and then decode it on the client side. An common example would be a base64-encoded string:
import io
import base64
...
def get_custom():
...
image = PIL.Image.open('file/path.png')
stream = io.StringIO()
image.save(stream, format='PNG')
return base64.b64encode(stream.getvalue())
Although not knowing anything about your REST endpoint design, a better solution in my opinion would be to declare a subresource with a separate view. Supposing you have a MyCustom resource in your REST schema accessible by api/mycustom/:id/ and served by MyCustomGet view, then e.g. a separate view could be responsible for offering the corresponding file under api/mycustom/:id/pic/:
import django.http
class MyCustomPicView(APIView):
def get(self, request):
...
image = PIL.Image.open('file/path.png')
return django.http.HttpResponse(image, content_type='image/png')
I'm not sure if this would be helpful, but this is what I did for a similar situation. I had one primary model object, and a semi-related object I wanted to tag in.
Basically, if your CustomClass model is somehow related to the image you need to include, just fetch it directly in the serializer instance.
This is sort of how I would try to do it:
class MyCustomSerializer(serializers.ModelSerializer):
image_binary = serializers.SerializerMethodField()
class Meta:
model = MyCustom
fields = '__all__'
def get_image_binary(self, obj):
return WhateverModel.objects.get(relation=obj).attribute
This simply adds some extra data to your model serializer, calculated on the fly by the serializer. You could even have a second serializer for the image_binary and in the get_image_binary() simply return the .data for the serializer, just like you did in your view.
This of course relies on the fact that the MyCustom object is somehow implicitly related to your image binary.
Firstly, in serializer you have mentioned model as MyCustom and your actual model name is CustomClass. Don't know if this is related or not. If image is the problem, you could convert the image to a string, and convert it back in the view/ wherever you want to use it.
class CustomClass:
obj = None
image = None
def get_custom():
r = CustomClass()
r.obj = MyCustom.objects.all().first()
import base64
with open("file/path.png", "rb") as imageFile:
str_ = base64.b64encode(imageFile.read())
r.image = str_
return r
To convert it back to an image:
fh = open("imageToSave.png", "wb")
fh.write(r.image.decode('base64'))
fh.close()
I don't know what your specific use case is, but this structure doesn't look right. I would use an ImageField to store the image, and in the serializer i would simply return image.url.

Type Error: is not JSON serializable

I`m trying to pass database objects from one view to another view. But when I try to achieve this using SESSION, I am getting this "is not JSON serializiable" error.
My Views.py:
def index(request):
listset = TheaterBase.objects.all()
request.session['s_listset'] = listset
def otherview(request):
result = request.session.get('s_listset')
How to pass the Database objects in between the views?
Thanks in advance
Server sessions can store JSON objects only. You are trying to store a complex Django QuerySet object, which naturally is not JSON serializable.
And trust me, even if it was, you wouldn't want to do this. It's not healthy to abuse your server's session with a high amount of data.
Let's just assume that your TheaterBase class is something like below(pseudo code)
class TheaterBase:
field1 ...
fielld2 ...
-------
# a method to produce json serializable representation
def as_dict(self):
return {'field1': self.field1, 'fileld2': self.fielld2}
Then on you view do
listset = [x.as_dict() for x in TheaterBase.objects.all()]
The issue here is the object coming out of your db query are not json serializable. The as_dict method above is constructing a json serializable representation of that object.
You can try using django serializers
from django.core import serializers
listset = serializers.serialize("json", TheaterBase.objects.all())

How to serialize Django queryset.values() into json?

I have a model that has many fields, however for this problem I only need 3 of those fields. When I try to serialize a .values set I get an exception:
'dict' object has no attribute '_meta'
This is my code:
queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = serializers.serialize('json', queryset, ensure_ascii=False)
As other people have said, Django's serializers can't handle a ValuesQuerySet. However, you can serialize by using a standard json.dumps() and transforming your ValuesQuerySet to a list by using list(). If your set includes Django fields such as Decimals, you will need to pass in DjangoJSONEncoder. Thus:
import json
from django.core.serializers.json import DjangoJSONEncoder
queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = json.dumps(list(queryset), cls=DjangoJSONEncoder)
Django serializers can only serialize queryset, values() does not return queryset rather ValuesQuerySet object. So, avoid using values(). Rather, specifiy the fields you wish to use in values(), in the serialize method as follows:
Look at this SO question for example
objectQuerySet = ConventionCard.objects.filter(ownerUser = user)
data = serializers.serialize('json', list(objectQuerySet), fields=('fileName','id'))
Instead of using objectQuerySet.values('fileName','id'), specify those fields using the fields parameter of serializers.serialize() as shown above.
Make list from objectQuerySet:
data_ready_for_json = list( ConventionCard.objects.filter(ownerUser = user).values('fileName','id') )
My solution, It's work fine
from django.core.serializers import serialize
import json
permission_list = Permission.objects.all().order_by('-id')
permission_serialize= json.loads(serialize('json', permission_list))
return JsonResponse({'data': permission_serialize})
Just cast to dict every item and create json with json.dumps:
json.dumps([dict(item) for item in SomeModel.objects.all().values('id', 'title')])
Try this:
queryset = myModel.objects.filter(foo_icontains=bar)
serialized_q = serializers.serialize(queryset, many = True)

Categories