3

I want to serialize a queryset of an object which has a one-to-many relationship to another model. I want to include the related objects in my json output.

Example:

class Book(models.Model):
    title = models.CharField()
    author = models.ForeignKey('Author')

class Author(models.Model):
    name = models.CharField()

view.py:

serializers.serialize('json', Author.objects.all()) #does not include the book objects

I am pretty sure there is an easy solution, but so far I was not able to figure out how to do it. Thanks for your help!

3 Answers3

6

You can't do it from default django serializer, because the Author model has not books field. You can achieve it by creating your own serializer or manually build your data and pass it to simplejson.dumps()

Update

For example:

class Author(models.Model):
    ...
    def get_json(self):
        return {
            'id': self.id, 
            'name': self.name,
            'books': [{'id': b.id, 'title': b.title} for b in self.book_set.all()] }

from django.utils import simplejson
simplejson.dumps([a.get_json() for a in Author.objects.all()])
A.J.
  • 8,557
  • 11
  • 61
  • 89
sneawo
  • 3,543
  • 1
  • 26
  • 31
1

Do you want to export your JSON data to a file? If so, you can also use the management command dumpdata:

python manage.py dumpdata your_app.Book your_app.Author > my_models.json

This would save the data of both models into the file my_models.json.

Instead, if you want to serialize your data to be used for AJAX requests or the like, you can wrap your model data in a dictionary. Do something like this in your view:

# The querysets must be wrapped in list()
# otherwise they can't be serialized as JSON objects
response = {  
    'authors': list(Author.objects.all()),
    'books': list(Book.objects.all())
}

return HttpResponse(simplejson.dumps(response), mimetype='application/json')
pemistahl
  • 9,304
  • 8
  • 45
  • 75
  • I try to export it to a template, so the latter option. Your suggestion probably works, but I want the book object to be integrated into the author object. If I follow your code they will be split to different data sets. – Adrian Debbeler Dec 27 '12 at 18:15
  • @user1887414 In this case it's probably better if you manually create a dictionary holding the authors as keys and for each author a list of their book titles as values. Then you export this dictionary to the template. – pemistahl Dec 27 '12 at 18:24
1

Last year, I needed something like that, working with Flask. I used this thread. It would give you something like this :

class Book(models.Model):
    title = models.CharField()
    author = models.ForeignKey('Author')

    @property
    def serialize(self):
        return {
            'title'    : self.title,
            'author'   : self.author.serialize
        }

class Author(models.Model):
    name = models.CharField()

    @property
    def serialize(self):
        return {
            'name'    : self.name
        }

    @property
    def serialize_books(self):
        return [ book.serialize for book in self.book_set.all() ]

Edit : this answer is pretty the same than @sneawo's one. The only difference is that you can chain serialize methods.

gabmichelet
  • 63
  • 1
  • 2
  • 6