python group - Requête Django qui obtient les objets les plus récents de différentes catégories




3 Answers

Pour autant que je sache, il n'y a pas de moyen unique de faire cela dans Django ORM.

Mais vous pouvez le diviser en deux requêtes:

bakeries = Bakery.objects.annotate(hottest_cake_baked_at=Max('cake__baked_at')) 
hottest_cakes = Cake.objects.filter(baked_at__in=[b.hottest_cake_baked_at for b in bakeries])

Si les ID des gâteaux progressent avec les horodatages bake_at, vous pouvez simplifier et désambiguïser le code ci-dessus (dans le cas où deux gâteaux arrivent en même temps, vous pouvez les obtenir tous les deux):

hottest_cake_ids = Bakery.objects.annotate(hottest_cake_id=Max('cake__id')).values_list('hottest_cak‌​e_id', flat=True)
hottest_cakes = Cake.objects.filter(id__in=hottest_cake_ids)

BTW crédits pour cela va à Daniel Roseman, qui a déjà répondu à une question similaire à moi:

http://groups.google.pl/group/django-users/browse_thread/thread/3b3cd4cbad478d34/3e4c87f336696054?hl=pl&q=

Si la méthode ci-dessus est trop lente, je connais également la seconde méthode - vous pouvez écrire du SQL personnalisé produisant uniquement les gâteaux les plus chauds dans les boulangeries pertinentes, le définir comme vue de la base de données, puis écrire le modèle Django non managé. Il est également mentionné dans le thread django-users ci-dessus. Lien direct vers le concept original est ici:

http://web.archive.org/web/20130203180037/http://wolfram.kriesing.de/blog/index.php/2007/django-nice-and-critical-article#comment-48425

J'espère que cela t'aides.

by date

J'ai deux modèles A et B Tous B objets B ont une clé étrangère à un objet A Étant donné un ensemble d'objets A , est-il possible d'utiliser l'ORM pour obtenir un ensemble d'objets B contenant l'objet le plus récent créé pour chaque objet A

Voici un exemple simplifié:

Class Bakery(models.Model):
    town = models.CharField()

Class Cake(models.Model):
    bakery = models.ForeignKey(Bakery)
    baked_at = models.DateTimeField()

Donc, je cherche une requête qui renvoie le gâteau le plus récent cuit dans chaque boulangerie à Anytown, États-Unis.




À partir de Django 1.11 et grâce à Subquery et OuterRef et nous pouvons enfin construire une requête latest-per-group utilisant l' ORM .

hottest_cakes = Cake.objects.filter(
    baked_at=Subquery(
        (Cake.objects
            .filter(bakery=OuterRef('bakery'))
            .values('bakery')
            .annotate(last_bake=Max('baked_at'))
            .values('last_bake')[:1]
        )
    )
)

#BONUS, we can now use this for prefetch_related()
bakeries = Bakery.objects.all().prefetch_related(
    Prefetch('cake_set',
        queryset=hottest_cakes,
        to_attr='hottest_cakes'
    )
)

#usage
for bakery in bakeries:
    print 'Bakery %s has %s hottest_cakes' % (bakery, len(bakery.hottest_cakes))



Je me battais avec un problème similaire et finalement arriver à la solution suivante. Il ne repose pas sur order_by et distinct donc peut être trié comme souhaité sur db-side et peut également être utilisé comme requête imbriquée pour le filtrage. Je crois aussi que cette implémentation est indépendante du moteur db, car elle est basée sur la clause SQL HAVING standard. Le seul inconvénient est qu'il retournera plusieurs gâteaux les plus chauds par boulangerie, s'ils sont cuits dans cette boulangerie exactement au même moment.

from django.db.models import Max, F

Cake.objects.annotate(
    # annotate with MAX "baked_at" over all cakes in bakery
    latest_baketime_in_bakery=Max('bakery__cake_set__baked_at')
    # compare this cake "baked_at" with annotated latest in bakery
).filter(latest_baketime_in_bakery__eq=F('baked_at'))



Related

python django django-queryset greatest-n-per-group