16

I am having some issue here. I am trying to return a JSON response made of a message and a model instance:

   class MachineModel(models.Model):
       name = models.CharField(max_length=64, blank=False)
       description = models.CharField(max_length=64, blank=False)
       manufacturer = models.ForeignKey(Manufacturer)
       added_by = models.ForeignKey(User, related_name='%(app_label)s_%(class)s_added_by')
       creation_date = models.DateTimeField(auto_now_add=True)
       last_modified = models.DateTimeField(auto_now=True)

    machine_model_model = form.save(commit=False)
    r_user = request.user.userprofile
    machine_model_model.manufacturer_id = manuf_id
    machine_model_model.added_by_id = request.user.id
    machine_model_model.save()
    alert_message = " The'%s' model " % machine_model_model.name
    alert_message += ("for '%s' " % machine_model_model.manufacturer)
    alert_message += "was was successfully created!"
    test = simplejson.dumps(list(machine_model_model))
    data = [{'message': alert_message, 'model': test}]
    response = JSONResponse(data, {}, 'application/json')


class JSONResponse(HttpResponse):
"""JSON response class."""
    def __init__(self, obj='', json_opts={}, mimetype="application/json", *args, **kwargs):
        content = simplejson.dumps(obj, **json_opts)
        super(JSONResponse,self).__init__(content, mimetype, *args, **kwargs)

But I keep getting:

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 178, in default
raise TypeError(repr(o) + " is not JSON serializable")

TypeError: <MachineModel: "Test12"> is not JSON serializable

Why is that? I have seen before:

models = Model.objects.filter(manufacturer_id=m_id)
json = simplejson.dumps(models)

and that works... what is the difference?!

Thanks!

0

2 Answers 2

20

You should use django serializers instead of simplejson:

For example, this returns correctly serialized data:

from django.core import serializers
# serialize queryset
serialized_queryset = serializers.serialize('json', some_queryset)
# serialize object
serialized_object = serializers.serialize('json', [some_object,])
Sign up to request clarification or add additional context in comments.

4 Comments

I don't really get a JSON object... I get "[{"pk": 86, "model": "machine_models.machinemodel", "fields": {"name": "MX10", "description": "lol", "creation_date": "2012-09-23T16:50:35.709Z", "last_modified": "2012-09-23T16:50:35.709Z", "added_by": 2, "manufacturer": "1"}}]"
It is actualy JSON object. You can deserialize it on a template. By jquery, for example: jQuery.parseJSON(response), which returns a javascript dictionary.
Ok good it works! But I always get an array (in JQuery and I have to take the first [0]... Is that normal?! It is kind of annoying as well. Would you recommend a REST Api?!
As the second argument of serialize method can be any iterator that yields Django model instances (taken from docs), I dont know any other method to handle with single model instance serialization. Also, checkout this relative question. About REST Api - sorry, I am not competent in this area. Btw, I use the same descriptions in my projects :-)
17

Method-1: Use Django's python serializer

I think this answer won't return a JSON or a Python dict/list object. So, use the format python instead of json

from django.core import serializers
# serialize queryset
serialized_queryset = serializers.serialize('python', some_queryset)
# serialize object
serialized_object = serializers.serialize('python', [some_object,])

Django shell response

In [2]: from django.core import serializers                                                                                                                             

In [3]: qs = SomeModel.objects.all()                                                                                                                                    

In [4]: json_res = serializers.serialize('json',qs)                                                                                                                     

In [5]: type(json_res)                                                                                                                                                  
Out[5]: str

In [6]: python_res = serializers.serialize('python',qs)                                                                                                                 

In [7]: type(python_res)                                                                                                                                                
Out[7]: list
#views.py
from django.core import serializers
from django.http.response import JsonResponse


def some_view(request):
    some_queryset = SomeModel.objects.all()
    serialized_queryset = serializers.serialize('python', some_queryset)
    return JsonResponse(serialized_queryset, safe=False)

Method-2: Use Django's values() method

The direct use of values() method will throw TypeError exception, so convert the QuerySet to a python list as below,

from django.http.response import JsonResponse


def sample_view(request):
    return JsonResponse(list(SomeModel.objects.all().values()), safe=False)

4 Comments

@Radesh What happened with method-1?
return json response contain some extra /" like this : [{\"model\": \"api\"
@JPG, is it equally the same to use either of these methods? Do any of these have any drawbacks in performance or another thing? I personally see using second method very easy but also curious about if it has any disadvantage.
I'm not a big fan of using safe=false, but in my application, I was able to put the list into a dictionary to make the JsonResponse serializer happy: return JsonResponse({ "someObjects": list(SomeModel.objects.all().values()) })

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.