views:

1375

answers:

6

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?

+1  A: 

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.

Jack M.
+1  A: 

What's wrong with serializing a QuerySet that has just a single model instance?

data = serializers.serialize("xml", SomeModel.objects.get(pk=1))
I know its anal but it wraps in two more layers than it has to. So you have to do data[0].fields.name instead of data.name.
Jason Christa
Right. That's the way it works. Serializing a singleton is an odd special case.
S.Lott
+3  A: 

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.

David Berger
I haven't tried the code yet but I just wanted to point out some errors in it. It is instance._meta.get_all_field_names() and __getattribute__ is a function so should have () and not [].
Jason Christa
Good points. Chock it up to bad typing.
David Berger
in addition to FK, this will not work for datetime fields (unless there is magic in demjson.JSON.encode)
skyl
A: 
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,....}

A: 

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.

davidchambers
+3  A: 

You can easily use a list to wrap the required object and that's all what django serializers need to correctly serialize it, eg.:

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
xaralis
+1 simple solutions are often the best.
Seth