web-dev-qa-db-fra.com

Django Aggregation - Expression contient des types mixtes. Vous devez définir output_field

J'essaie de réaliser une requête d'agrégation et c'est mon code:

TicketGroup.objects.filter(event=event).aggregate(
                           total_group=Sum(F('total_sold')*F('final_price')))

J'ai 'total_sold' et 'final_price' dans l'objet TicketGroup et tout ce que je veux faire, c'est additionner et multiplier les valeurs pour obtenir le total vendu de tous les TicketGroups ensemble.

Tout ce que je reçois est cette erreur:

L'expression contient des types mixtes. Vous devez définir output_field

Qu'est-ce que je fais mal, puisque j'appelle 'total_group' comme champ de sortie?

Merci!

18
Lara

Par output_field Django signifie fournir le type de champ pour le résultat de Sum.

from Django.db.models import FloatField, F
total_group=Sum(F('total_sold')*F('final_price'), output_field=FloatField())

devrait faire l'affaire.

34
Todor

J'ai dû utiliser quelque chose de différent pour que ma requête fonctionne. Juste output_field ne le résoudra pas. J'avais besoin d'une simple division entre deux alias. Ce sont la sortie de deux annotations.

from Django.db.models import FloatField, ExpressionWrapper, F

distinct_people_with_more_than_zero_bill = Task.objects.filter(
    billable_efforts__gt=0).values('report__title').annotate(
    Count('assignee', distinct=True)).annotate(
    Sum('billable_efforts'))

annotate(yy=ExpressionWrapper(F('billable_efforts__sum') / F('assignee__count'), output_field=FloatField()))

La clé ici est ExpressionWrapper . Sans cela, vous obtiendrez une erreur: non-expression (s) reçue

L'astuce est venue pour la documentation Django elle-même, qui dit:

Si les champs que vous combinez sont de types différents, vous devrez indiquer Django quel type de champ sera renvoyé. Puisque F() ne ne prend pas directement en charge le champ de sortie, vous devrez envelopper l'expression avec ExpressionWrapper

Lien: https://docs.djangoproject.com/en/2.2/ref/models/expressions/

7