2010-05-15 6 views
2

Voici mon modèle simplifié:requête d'agrégation Django sur afférant-à-plusieurs objets

class Item(models.Model): 
    pass 

class TrackingPoint(models.Model): 
    item = models.ForeignKey(Item) 
    created = models.DateField() 
    data = models.IntegerField() 

    class Meta: 
     unique_together = ('item', 'created') 

Dans de nombreuses parties de mon application, je dois récupérer un ensemble de Item « s et annoter chaque élément avec data champ de la dernière TrackingPoint de chaque article commandé par created domaine. Par exemple, par exemple i1 de classe Item a 3 TrackingPoint « s:

tp1 = TrackingPoint(item=i1, created=date(2010,5,15), data=23) 
tp2 = TrackingPoint(item=i1, created=date(2010,5,14), data=21) 
tp3 = TrackingPoint(item=i1, created=date(2010,5,12), data=120) 

je besoin d'une requête pour récupérer i1 exemple annotée avec tp1.data valeur du champ comme tp1 est le dernier point de suivi commandé par created terrain. Cette requête devrait également retourner Item qui n'ont aucun TrackingPoint du tout. Si possible, je préfère ne pas utiliser la méthode extra de QuerySet pour ce faire.

C'est ce que j'ai essayé jusqu'à présent ... et a échoué :(

Item.objects.annotate(max_created=Max('trackingpoint__created'), 
         data=Avg('trackingpoint__data')).filter(trackingpoint__created=F('max_created')) 

Toutes les idées?

Répondre

1

Cela ne répond directement à votre question, mais dans le cas où ne pas besoin exactement ce vous décrit, vous pourriez être intéressé par le plus grand-n-par-groupe solution vous pouvez jeter un oeil sur ma réponse sur la même question.

Django Query That Get Most Recent Objects From Different Categories

- t son devrait appliquer directement à votre cas:

items = Item.objects.annotate(tracking_point_created=Max('trackingpoint__created')) 
trackingpoints = TrackingPoint.objects.filter(created__in=[b.tracking_point_created for b in items]) 

Notez que deuxième ligne peut produire des résultats ambigus si created dates répètent dans le modèle TrackingPoint.

+0

Votre solution parcourt tous les 'items', je ne peux pas me le permettre. 'created' est unique dans un article, j'ai mis à jour ma question. – parxier

6

est ici une seule requête qui fournira (TrackingPoint, article) -pairs:

TrackingPoint.objects.annotate(max=Max('item__trackingpoint__created')).filter(max=F('created')).select_related('item').order_by('created') 

Vous auriez à interroger des articles sans TrackingPoints séparément.

+0

Merci, cela a fonctionné parfaitement! – Jeff

+0

ne savait pas sur select_related - à la vôtre – frankster