2017-08-07 5 views
0

J'ai trois modèles:Django Queryset - Comment faire des maths sur des modèles liés avec prefetch_related?

class Variety(models.Model) 
    name = models.CharField(max_length=24) 

class Item(models.Model) 
    name = models.CharField(max_length=24) 
    in_stock = models.IntegerField() 

class ItemPart(models.Model)   
    variety = models.ForeignKey(Variety) 
    product = models.ForeignKey(Product) 
    qty = models.IntegerField() 

Je voudrais dire combien de chaque variété a été transformée en produits en obtenant tous les ItemParts liés et en multipliant leur qty par le in_stock de leurs articles connexes.

Je suis arrivé jusqu'ici:

Variety.objects.all().prefetch_related('itempart_set').values('name').annotate(
    Sum(F("itempart_set__qty") * F("itempart_set__item_set__in_stock") 
) 

Est-ce que ce travail? Va-t-il additionner les produits, ou simplement multiplier les sommes?

+0

"Est-ce que cela fonctionnera?" L'as tu essayé_? Sûrement cela aurait été plus facile que de poser une question sur Stack Overflow ... – Chris

+0

Eh bien, j'essaie de concevoir correctement mes modèles. Donc je devrais les construire, mettre dans un tas de données fausses et l'essayer. J'espérais que quelqu'un pourrait confirmer avant que je prenne la peine de leur donner tort. –

Répondre

1

Vous ne pouvez pas faire de calcul avec les modèles interrogés par prefetch_related car prefetch_related frappe la base de données séparément de la requête originale. Votre requête est probablement évaluée à deux requêtes de base de données et maths au niveau de la base de données est hors de question dans ce cas. Maintenant, je ne dis pas que la requête ci-dessus ne fonctionnera pas (Django travaille sa magie et après tout, nous ne savons pas quelle version vous utilisez), mais je dis que le prefetch_related sera pas vous donner un coup de pouce de performance pour le calcul.

Si ce qui précède ne fonctionne pas, j'essaierais de le faire avec des sous-requêtes introduites dans Django 1.11.

+0

Merci! C'est ce que je voulais savoir. –

+0

@AdamStarrh Si c'est ce que vous vouliez savoir, alors peut-être le marquer comme la bonne réponse aussi? – makaveli

+1

Je pensais avoir cliqué dessus. Merci pour la capture –