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.
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.
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.
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()))
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With