Mam querySet z książkami i chciałbym dodać pole score do każdego wyniku książek.

qs = Book.objects.all()

W surowym SQL napisałbym:

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;

Jak mogę to osiągnąć w Django? Próbowałem annotate(), ale wydaje się, że nie jest to przeznaczone do tego rodzaju rzeczy.

18
dev9 14 sierpień 2014, 17:08

2 odpowiedzi

Najlepsza odpowiedź

Jeśli głosy możliwe wartości są tylko 1 i -1, możesz po prostu sumować ich przy użyciu wymienionego Adnotate: Book.objects.annotate(score=Sum('votes__value')).

Jeśli istnieje więcej możliwych wartości, możesz filtrować adnotację, dodając .filter(votes__value__range=(1,1)) do powyższego zapytania.

Jeśli jest bardziej złożony, musiałbyś użyć extra za pomocą select.

5
ambi 14 sierpień 2014, 13:44

Surowy SQL jest nie jedyny sposób. Możesz użyć wyrażenia Value() (patrz Dokumenty tutaj):

from django.db.models import CharField, Value

MyModel.objects.all().annotate(mycolumn=Value('xxx', output_field=CharField()))
41
javidazac 3 październik 2018, 22:22