views:

378

answers:

3

I have two models A and B. All B objects have a foreign key to an A object. Given a set of A objects, is there anyway to use the ORM to get a set of B objects containing the most recent object created for each A object

Here's an simplified example:

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

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

So I'm looking for a query that returns the most recent cake baked in each bakery in Anytown, USA.

Thanks

+3  A: 

This should do the job:

from django.db.models import Max
Bakery.objects.annotate(Max('cake__baked_at'))
Daniel Roseman
That is nice, have to learn those annotates finally.
gruszczy
I haven't tested yet, but that looks like it will annotate the time that each bakery most recently baked a cake. I'm looking for for the actual cake objects. Am I misinterpreting your answer?
Zach
@Zach: no, I think you're right
Tomasz Zielinski
Yes, you're right. I had forgotten the previous answer I posted for Tomasz :-)
Daniel Roseman
+2  A: 

As far as I know, there is no one-step way of doing this in Django ORM.

But you can split it in two queries:

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])

If id's of cakes are progressing along with bake_at timestamps, you can simplify and disambiguate the above code (in case two cakes arrives at the same time you can get both of them):

bakeries = Bakery.objects.annotate(hottest_cake_id=Max('cake__id')) 
hottest_cakes = Cake.objects.filter(id__in=[b.hottest_cake_id for b in bakeries])

BTW credits for this goes to Daniel Roseman, who once answered similar question of mine:

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

If the above method is too slow, then I know also second method - you can write custom SQL producing only those Cakes, that are hottest in relevant Bakeries, define it as database VIEW, and then write unmanaged Django model for it. It's also mentioned in the above django-users thread. Direct link to the original concept is here:

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

Hope this helps.

Tomasz Zielinski
I'll probably go with the second set of queries you suggested. Thanks.
Zach
A: 

Take a look at django.views.generic.date_based.archive_index. http://docs.djangoproject.com/en/dev/ref/generic-views/ It can find the latest objects from a queryset.

RJBrady