Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add additional column to Django QuerySet

I have a QuerySet with Books and I would like to add a score field to every Book result.

qs = Book.objects.all()

In raw SQL I would write:

SELECT
    *,
    (
        (SELECT COUNT(*) FROM votes WHERE value=1 AND book=b.id) - 
        (SELECT COUNT(*) FROM votes WHERE value=-1 AND book=b.id)
    ) AS score
FROM
    Book b;

How can I achieve it in Django? I tried annotate(), but it seems it's not meant for this kind of stuff.

like image 967
dev9 Avatar asked Aug 14 '14 13:08

dev9


People also ask

How do I append QuerySet in Django?

Use union operator for queryset | to take union of two queryset. If both queryset belongs to same model / single model than it is possible to combine querysets by using union operator. One other way to achieve combine operation between two queryset is to use itertools chain function.

What is QuerySet in Django with example?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data.


2 Answers

Raw SQL is not the only way. You can use a Value() expression (see docs here):

from django.db.models import CharField, Value

MyModel.objects.all().annotate(mycolumn=Value('xxx', output_field=CharField()))
like image 157
Joseph Avatar answered Oct 04 '22 17:10

Joseph


If votes possible values are only 1 and -1 you can just sum them using mentioned annotate: Book.objects.annotate(score=Sum('votes__value')).

If there is more possible values you can filter annotation by adding .filter(votes__value__range=(1,1)) to the above query.

If it's more complex you would have to use extra with select.

like image 45
ambi Avatar answered Oct 01 '22 17:10

ambi