Deserializing JSON in Django - django

This one has had me pulling out my hair. I've been trying to deserialize JSON in Django for the last couple hours.
I have a function:
# in index.html
function updateWidgetData(){
var items=[];
for statement here:
for statement here:
var item={
id: $j(this).attr('id'),
collapsed: collapsed,
order : i,
column: columnId
};
items.push(item);
var sortorder={ items: items};
$j.post('2', 'data='+$j.toJSON(sortorder), function(response)
{
if(response=="success")
$j("#console").html('<div class="success">Saved</div>').hide().fadeIn(1000);
setTimeout(function(){
$j('#console').fadeOut(1000);
}, 2000);
});
}
And I'm trying to deserialize the JSON in django:
# in views.py
if request.is_ajax():
for item in serializers.deserialize("json", request.content):
item = MyObject(id=id, collapsed=collapsed, order=order, column=column)
return HttpResponse("success")
else:
....
And it hasn't been working. I know this is probably a really trivial question, but I've never used JSON before, and I'd really appreciate some help. Thanks!

serializers.deserialize is for deserializing a particular type of JSON - that is, data that was serialized from model instances using serializers.serialize. For your data, you just want the standard simplejson module.
And the second thing wrong is that your response isn't just JSON - it is an HTTP POST with JSON in the data field. So:
from django.utils import simplejson
data = simplejson.loads(request.POST['data'])

from django.core import serializers
obj_generator = serializers.json.Deserializer(request.POST['data'])
for obj in obj_generator:
obj.save()
Objects should now be saved and visible in django admin

Related

Serialize data to json formate using native serializer Django

I have this dictionary which I need to pass to another view, knowing that possible ways of doing that are either through sessions or cache, now when I am trying to pass to session it is throwing me an error that data is not JSON serializable probably because I have DateTime fields inside this dictionary
session_data = serializers.serialize('json',session_data)
error on above statement
'str' object has no attribute '_meta'
updated
date is somewhat in this format
{'city_name': 'Srinagar', 'description': 'few clouds', 'temp': 26.74, 'feels_like': 27.07, 'max_temp': 26.74, 'min_temp': 26.74, 'sunrise': datetime.time(6, 11, 10), 'sunset': datetime.time(18, 43, 59)}
Your session_data is already a dictionary. Since Django's serializer focuses on serializing an iterable of model object, that thus will not work.
You can make use of Django's DjangoJSONEncoder [Django-doc] to serialize Python objects that include date, datetime, time and/or timedelta objects.
You thus can work with:
from django.core.serializers.json import DjangoJSONEncoder
encoder = DjangoJSONEncoder()
session_data = encoder.encode(session_data)
If you plan to return a JSON blob as a HTTP response, you can simply let the JsonResponse do the encoding work:
from django.http import JsonResponse
# …
return JsonResponse(session_data)

Get data from JsonResponse in django

I wanted to know how to get data from a JsonResponse in django. I made a JsonResponse that works like this
def pfmdetail(rsid):
snpid = parseSet(rsid)
if not snpid:
return HttpResponse(status=404)
try:
data = SnpsPfm.objects.values('start', 'strand', 'type', 'scoreref', 'scorealt',
rsid=F('snpid__rsid'), pfm_name=F('pfmid__name')).filter(snpid=snpid[0])
except SnpsPfm.DoesNotExist:
return HttpResponse(status=404)
serializer = SnpsPfmSerializer(data, many=True)
return JsonResponse(serializer.data, safe=False)
and then I call directly the method like this
def pfmTable(qset,detail):
source = pfmdetail(detail)
print(source)
df = pd.read_json(source)
but it gives me an error. I know it's wrong because with the print it returns the status of the response which is 200 so I suppose that the response is fine but how can I access the data inside the response? I tried import json to do json.load but with no success. I even tried the methods of QueryDict but stil I can't acess to the content I'm interested
P.S. I know that data contains something because if i display the jsonresponse on the browser i can see the JSON
As you can see here: https://docs.djangoproject.com/en/2.2/ref/request-response/#jsonresponse-objects.
JsonResponse object holds json in its content attribute.
So to access it try this:
df = pd.read_json(source.content)
Or to see it printed do:
print(source.content)
If you aren't using pandas, then you should process the content attribute of the JSONResponse object like this:
r = json.loads(source.decode())
I got the answer here: How to parse binary string to dict ?

JSON Serializing in Django and JSON Parsing in Jquery

So I have this code:
def success_comment_post(request):
if "c" in request.GET:
c_id = request.GET["c"]
comment = Comment.objects.get(pk=c_id)
model = serializers.serialize("json", [comment])
data = {'message': "Success message",
'message_type': 'success',
'comment': model }
response = JSONResponse(data, {}, 'application/json')
return response
else:
data = {'message': "An error occured while adding the comment.",
'message_type': 'alert-danger'}
response = JSONResponse(data, {}, 'application/json')
and back in jQuery I do the following:
$.post($(this).attr('action'), $(this).serialize(), function(data) {
var comment = jQuery.parseJSON(data.comment)[0];
addComment($("#comments"), comment);
})
Now... in the Django function, why do I have to put the comment in [] -->
model = serializers.serialize("json", [comment])
and back in jQuery, why do I have to do jQuery.parseJSON(data.comment)[0]?
Anyway I don't have to do this? I find it weird I have to hardcode the [0]
Thanks a lot!
Well serializers.serialize only takes querysets or iterators with django model instances but using Comment.objects.get will return an object and not an iterator and that is why you will need to put it in [] to make it an iterator.
Since its a list you will have to access it like an array in javascript too. I would suggest not using serializer and using simplejson to convert field values to json.
Sample Code:
from django.utils import simplejson as json
from django.forms.models import model_to_dict
comment = Comment.objects.get(pk=c_id)
data = {'message': "Success message",
'message_type': 'success',
'comment': model_to_dict(comment)}
return HttpResponse(json.dumps(data), mimetype='application/json')
I have only mentioned relevant parts of your code. Hopefully this should solve your problem

Django- Many to Many field querying

I have following structure of models in django :
class BodySubPart(models.Model):
body_subpart=models.CharField(max_length=20)
def __str__(self):
return self.body_subpart
class BodyPart(models.Model):
body_part=models.CharField(max_length=20)
body_subpart=models.ManyToManyField(BodySubPart)
def __str__(self):
return self.body_part
Ex:
example,
if BodyPart=head then BodySubPart= face,mouth,eyes,nose.
if BodyPart=arm then BodySubPart= shoulder,fingers,elbow.
like this many body parts are stored.
...
now I want to create a runtime form have two choicefields (BodySubPart and BodyPart) such that when i select the BodyPart it should change the list in BodySubPart.
Ex.
The first choicefield has body parts={head,arm,chest...}
The second choice field should change when i select a particular part
If i select "head" then second choice field should show,
body sub parts={face,mouth,eyes,nose...}
Please help me here.....
What have you tried?? I think you will find people are more willing to help you if you have actually tried something yourself and not just want others to do it for you. It should go something like this:
1) BodyPart.objects.all() # all body parts
2) head = BodyPart.objects.get(body_part='head')
head_subparts = head.body_subpart.all() # all head subparts
django does a great job of explaining how to query these relationships.
https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships
In addition there are a number of really great tutorials online regarding djangos' manytomany relationships.
This requires a bit of AJAX, so first step is to create a view to handle that:
from django.core import serializers
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import get_list_or_404
def ajax_get_bodysubparts(request):
bodypart_id = request.GET.get('bodypart_id')
if bodypart_id:
bodysubparts = get_list_or_404(BodySubPart, bodypart__id=bodypart_id)
data = serializers.serialize('json', bodysubparts)
return HttpResponse(data, mimetype='application/json')
else:
return HttpResponseBadRequest()
Tie that to some URL in urls.py. Then, some JavaScript for your form (assumes jQuery):
$(document).ready(function(){
$('#id_bodypart').change(function(){
var selected = $(this).val();
if (selected) {
$.getJSON('/url/to/ajax/view/', {
'bodypart_id': selected
}, function (data, jqXHR) {
options = [];
for (var i=0; i<data.length; i++) {
options.append('<option value="'+data[i].id+'">'+data[i].body_subpart+'</option>');
}
$('#id_bodysubpart).html(options.join(''));
});
}
});
});
You will probably need a combination of custom form fields and widgets to get what you want.
Check out the django-ajax-filtered-fields project to see if that is close what you are looking for. It will at least provide some guidance if you decide to create your own.
You will need some javascript to make a new request to populate your fields dynamically, so that will also not be available with standard django forms.

How do you serialize a model instance in Django?

There is a lot of documentation on how to serialize a Model QuerySet but how do you just serialize to JSON the fields of a Model Instance?
You can easily use a list to wrap the required object and that's all what django serializers need to correctly serialize it, eg.:
from django.core import serializers
# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
If you're dealing with a list of model instances the best you can do is using serializers.serialize(), it gonna fit your need perfectly.
However, you are to face an issue with trying to serialize a single object, not a list of objects. That way, in order to get rid of different hacks, just use Django's model_to_dict (if I'm not mistaken, serializers.serialize() relies on it, too):
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 to serialize it to json:
import json
serialized = json.dumps(dict_obj)
That's it! :)
To avoid the array wrapper, remove it before you return the response:
import json
from django.core import serializers
def getObject(request, id):
obj = MyModel.objects.get(pk=id)
data = serializers.serialize('json', [obj,])
struct = json.loads(data)
data = json.dumps(struct[0])
return HttpResponse(data, mimetype='application/json')
I found this interesting post on the subject too:
http://timsaylor.com/convert-django-model-instances-to-dictionaries
It uses django.forms.models.model_to_dict, which looks like the perfect tool for the job.
There is a good answer for this and I'm surprised it hasn't been mentioned. With a few lines you can handle dates, models, and everything else.
Make a custom encoder that can handle models:
from django.forms import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Model
class ExtendedEncoder(DjangoJSONEncoder):
def default(self, o):
if isinstance(o, Model):
return model_to_dict(o)
return super().default(o)
Now use it when you use json.dumps
json.dumps(data, cls=ExtendedEncoder)
Now models, dates and everything can be serialized and it doesn't have to be in an array or serialized and unserialized. Anything you have that is custom can just be added to the default method.
You can even use Django's native JsonResponse this way:
from django.http import JsonResponse
JsonResponse(data, encoder=ExtendedEncoder)
It sounds like what you're asking about involves serializing the data structure of a Django model instance for interoperability. The other posters are correct: if you wanted the serialized form to be used with a python application that can query the database via Django's api, then you would wan to serialize a queryset with one object. If, on the other hand, what you need is a way to re-inflate the model instance somewhere else without touching the database or without using Django, then you have a little bit of work to do.
Here's what I do:
First, I use demjson for the conversion. It happened to be what I found first, but it might not be the best. My implementation depends on one of its features, but there should be similar ways with other converters.
Second, implement a json_equivalent method on all models that you might need serialized. This is a magic method for demjson, but it's probably something you're going to want to think about no matter what implementation you choose. The idea is that you return an object that is directly convertible to json (i.e. an array or dictionary). If you really want to do this automatically:
def json_equivalent(self):
dictionary = {}
for field in self._meta.get_all_field_names()
dictionary[field] = self.__getattribute__(field)
return dictionary
This will not be helpful to you unless you have a completely flat data structure (no ForeignKeys, only numbers and strings in the database, etc.). Otherwise, you should seriously think about the right way to implement this method.
Third, call demjson.JSON.encode(instance) and you have what you want.
If you want to return the single model object as a json response to a client, you can do this simple solution:
from django.forms.models import model_to_dict
from django.http import JsonResponse
movie = Movie.objects.get(pk=1)
return JsonResponse(model_to_dict(movie))
If you're asking how to serialize a single object from a model and you know you're only going to get one object in the queryset (for instance, using objects.get), then use something like:
import django.core.serializers
import django.http
import models
def jsonExample(request,poll_id):
s = django.core.serializers.serialize('json',[models.Poll.objects.get(id=poll_id)])
# s is a string with [] around it, so strip them off
o=s.strip("[]")
return django.http.HttpResponse(o, mimetype="application/json")
which would get you something of the form:
{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}
.values() is what I needed to convert a model instance to JSON.
.values() documentation: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values
Example usage with a model called Project.
Note: I'm using Django Rest Framework
from django.http import JsonResponse
#csrf_exempt
#api_view(["GET"])
def get_project(request):
id = request.query_params['id']
data = Project.objects.filter(id=id).values()
if len(data) == 0:
return JsonResponse(status=404, data={'message': 'Project with id {} not found.'.format(id)})
return JsonResponse(data[0])
Result from a valid id:
{
"id": 47,
"title": "Project Name",
"description": "",
"created_at": "2020-01-21T18:13:49.693Z",
}
I solved this problem by adding a serialization method to my model:
def toJSON(self):
import simplejson
return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))
Here's the verbose equivalent for those averse to one-liners:
def toJSON(self):
fields = []
for field in self._meta.fields:
fields.append(field.name)
d = {}
for attr in fields:
d[attr] = getattr(self, attr)
import simplejson
return simplejson.dumps(d)
_meta.fields is an ordered list of model fields which can be accessed from instances and from the model itself.
Here's my solution for this, which allows you to easily customize the JSON as well as organize related records
Firstly implement a method on the model. I call is json but you can call it whatever you like, e.g.:
class Car(Model):
...
def json(self):
return {
'manufacturer': self.manufacturer.name,
'model': self.model,
'colors': [color.json for color in self.colors.all()],
}
Then in the view I do:
data = [car.json for car in Car.objects.all()]
return HttpResponse(json.dumps(data), content_type='application/json; charset=UTF-8', status=status)
Use list, it will solve problem
Step1:
result=YOUR_MODELE_NAME.objects.values('PROP1','PROP2').all();
Step2:
result=list(result) #after getting data from model convert result to list
Step3:
return HttpResponse(json.dumps(result), content_type = "application/json")
Use Django Serializer with python format,
from django.core import serializers
qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)
What's difference between json and python format?
The json format will return the result as str whereas python will return the result in either list or OrderedDict
To serialize and deserialze, use the following:
from django.core import serializers
serial = serializers.serialize("json", [obj])
...
# .next() pulls the first object out of the generator
# .object retrieves django object the object from the DeserializedObject
obj = next(serializers.deserialize("json", serial)).object
All of these answers were a little hacky compared to what I would expect from a framework, the simplest method, I think by far, if you are using the rest framework:
rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)
This uses the Serializer directly, respecting the fields you've defined on it, as well as any associations, etc.
It doesn't seem you can serialize an instance, you'd have to serialize a QuerySet of one object.
from django.core import serializers
from models import *
def getUser(request):
return HttpResponse(json(Users.objects.filter(id=88)))
I run out of the svn release of django, so this may not be in earlier versions.
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......
return HttpResponse(simplejson.dumps(ville.__dict__))
I return the dict of my instance
so it return something like {'field1':value,"field2":value,....}
how about this way:
def ins2dic(obj):
SubDic = obj.__dict__
del SubDic['id']
del SubDic['_state']
return SubDic
or exclude anything you don't want.
This is a project that it can serialize(JSON base now) all data in your model and put them to a specific directory automatically and then it can deserialize it whenever you want... I've personally serialized thousand records with this script and then load all of them back to another database without any losing data.
Anyone that would be interested in opensource projects can contribute this project and add more feature to it.
serializer_deserializer_model
Let this is a serializers for CROPS, Do like below. It works for me, Definitely It will work for you also.
First import serializers
from django.core import serializers
Then you can write like this
class CropVarietySerializer(serializers.Serializer):
crop_variety_info = serializers.serialize('json', [ obj, ])
OR you can write like this
class CropVarietySerializer(serializers.Serializer):
crop_variety_info = serializers.JSONField()
Then Call this serializer inside your views.py
For more details, Please visit https://docs.djangoproject.com/en/4.1/topics/serialization/
serializers.JSONField(*args, **kwargs) and serializers.JSONField() are same. you can also visit https://www.django-rest-framework.org/api-guide/fields/ for JSONField() details.