<Django object > is not JSON serializable
Asked Answered
S

9

169

I have the following code for serializing the queryset:

def render_to_response(self, context, **response_kwargs):

    return HttpResponse(json.simplejson.dumps(list(self.get_queryset())),
                        mimetype="application/json")

And following is my get_quersety()

[{'product': <Product: hederello ()>, u'_id': u'9802', u'_source': {u'code': u'23981', u'facilities': [{u'facility': {u'name': {u'fr': u'G\xe9n\xe9ral', u'en': u'General'}, u'value': {u'fr': [u'bar', u'r\xe9ception ouverte 24h/24', u'chambres non-fumeurs', u'chambres familiales',.........]}]

Which I need to serialize. But it says not able to serialize the <Product: hederello ()>. Because the list is composed of both django objects and dicts. Any ideas?

Subtype answered 28/5, 2013 at 11:0 Comment(2)
Duplicated: https://mcmap.net/q/48302/-convert-django-model-object-to-dict-with-all-of-the-fields-intactVisakhapatnam
Does this answer your question? Convert Django Model object to dict with all of the fields intactShandrashandrydan
A
171

simplejson and json don't work with django objects well.

Django's built-in serializers can only serialize querysets filled with django objects:

data = serializers.serialize('json', self.get_queryset())
return HttpResponse(data, content_type="application/json")

In your case, self.get_queryset() contains a mix of django objects and dicts inside.

One option is to get rid of model instances in the self.get_queryset() and replace them with dicts using model_to_dict:

from django.forms.models import model_to_dict

data = self.get_queryset()

for item in data:
   item['product'] = model_to_dict(item['product'])

return HttpResponse(json.simplejson.dumps(data), mimetype="application/json")
Alfonso answered 28/5, 2013 at 11:4 Comment(5)
Now getting error --> 'NoneType' object has no attribute 'concrete_model' ... And using Django 1.4+Subtype
When the model has a datetime field, it does not work.Bleary
that solution will trigger a lot of queriesVisakhapatnam
to use that directly in JS, just use the safe tage. https://mcmap.net/q/145169/-passing-objects-from-django-to-javascript-domFalstaffian
is there also a way back? besides, you will override the product in your solution if it happens that there are more items in dataExhibitive
R
126

The easiest way is to use a JsonResponse.

For a queryset, you should pass a list of the the values for that queryset, like so:

from django.http import JsonResponse

queryset = YourModel.objects.filter(some__filter="some value").values()
return JsonResponse({"models_to_return": list(queryset)})
Richy answered 13/12, 2016 at 20:7 Comment(1)
thanks for .values(), In my case, I just need to add .values() after filterPrecedency
I
28

I found that this can be done rather simple using the ".values" method, which also gives named fields:

result_list = list(my_queryset.values('first_named_field', 'second_named_field'))
return HttpResponse(json.dumps(result_list))

"list" must be used to get data as iterable, since the "value queryset" type is only a dict if picked up as an iterable.

Documentation: https://docs.djangoproject.com/en/1.7/ref/models/querysets/#values

Illiteracy answered 7/10, 2014 at 16:32 Comment(1)
This worked well for me. Even though the error message suggests it's all in one big list, the list() is still apparently needed.Pinch
I
27

From version 1.9 Easier and official way of getting json

from django.http import JsonResponse
from django.forms.models import model_to_dict


return JsonResponse(  model_to_dict(modelinstance) )
Ist answered 13/10, 2016 at 17:59 Comment(0)
F
15

Another great way of solving it while using a model is by using the values() function.

def returnResponse(date):
    response = ScheduledDate.objects.filter(date__startswith=date).values()
    return Response(response)

Foxworth answered 6/11, 2020 at 18:44 Comment(0)
W
14

Our js-programmer asked me to return the exact JSON format data instead of a json-encoded string to her.

Below is the solution.(This will return an object that can be used/viewed straightly in the browser)

import json
from xxx.models import alert
from django.core import serializers

def test(request):
    alert_list = alert.objects.all()

    tmpJson = serializers.serialize("json",alert_list)
    tmpObj = json.loads(tmpJson)

    return HttpResponse(json.dumps(tmpObj))
Woollyheaded answered 27/9, 2018 at 7:31 Comment(1)
Will be better just HttpResponse(tmpObj)Graniela
S
9

First I added a to_dict method to my model ;

def to_dict(self):
    return {"name": self.woo, "title": self.foo}

Then I have this;

class DjangoJSONEncoder(JSONEncoder):

    def default(self, obj):
        if isinstance(obj, models.Model):
            return obj.to_dict()
        return JSONEncoder.default(self, obj)


dumps = curry(dumps, cls=DjangoJSONEncoder)

and at last use this class to serialize my queryset.

def render_to_response(self, context, **response_kwargs):
    return HttpResponse(dumps(self.get_queryset()))

This works quite well

Subtype answered 28/5, 2013 at 12:20 Comment(0)
E
1

For Django Model, try:

users = User.objects.all()   
return JsonResponse ({'data' : list(users)}) 
Extremity answered 27/9, 2022 at 17:44 Comment(0)
B
0

You can use this for the Django model. Here we get rid of the wrapper because of safe=False, without it there will be an error. But .values() will return you the key->value in a multidimensional array

views.py

from django.http import JsonResponse
users = User.objects.all().values()
return JsonResponse(list(users), safe=False)
Bihar answered 17/10, 2023 at 0:6 Comment(1)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Rackety

© 2022 - 2024 — McMap. All rights reserved.