12

How can you include annotated results in a serialized QuerySet?

data = serializer.serialize(Books.objects.filter(publisher__id=id).annotate(num_books=Count('related_books')), use_natural_keys=True)

However the key/value pare {'num_books': number} is not include into the json result.

I've been searching for similar questions on the internet, but i didn't found a solution that worked for me.

Here is a similar case: http://python.6.x6.nabble.com/How-can-you-include-annotated-results-in-a-serialized-QuerySet-td67238.html

Thanks!

Nunovsky
  • 365
  • 4
  • 18

4 Answers4

13

I did some research and found that serializer.serialize can only serialize queryset, and annotation just adds an attribute with each object of the queryset, so when you try to serialize a query, annotated fields aren't shown. This is my way of implementation:

from django.core.serializers.json import DjangoJSONEncoder

books = Books.objects.filter(publisher__id=id).annotate(num_books=Count('related_books')).values()
json_data = json.dumps(list(books), cls=DjangoJSONEncoder)
ruddra
  • 50,746
  • 7
  • 78
  • 101
9

As shown in this post you can use SerializerMethodField in your Serializer:

class BooksSerializer(serializers.ModelSerializer):

  num_books = serializers.SerializerMethodField()

  def get_num_books(self, obj):
    try:
        return obj.num_books
    except:
        return None

It will serialize the annotated value (readonly)

Martin Faucheux
  • 884
  • 9
  • 26
1

Based on the link, this has been solved by pull request (https://github.com/django/django/pull/1176) some months ago.

You need to add num_books as a property:

class Publisher():
    ....

    @property
    def num_books(self):
        return some_way_to_count('related_books')

and then call it like so:

data = serializer.serialize(Books.objects.filter(publisher__id=id)), use_natural_keys=True, extra=['num_books'])

I'm not too sure about the exact syntax, since I don't work much with serializers.

klasske
  • 2,164
  • 1
  • 24
  • 31
  • Thanks for the help, but i can't make it work. Also, if my Model is the Django built in User (`from django.contrib.auth.models import User`) how do you do it? – Nunovsky Aug 20 '14 at 16:41
  • 1
    As of October 2017, the pull request has been closed without being merged, and the ticket is still open. – seb Oct 20 '17 at 08:03
-1

To get count from specific columns, you must declare them via values method

>>>> Books.objects.filter(publisher__id=id).values('<group by field>').annotate(num_books=Count('related_books'))
[{'num_books': 1, '<group by field>': X}]
xecgr
  • 5,095
  • 3
  • 19
  • 28