views:

79

answers:

2

Suppose I have these two models:

class Blog(models.Model):
    name = models.CharField(max_length=64)
    # ...

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    added = models.DateTimeField(auto_now_add=True)
    # ...

Now I want to get a list of all blogs along with the latest blog entry for each respective blog. What's the best way to do it?

If it makes any difference, we can assume that each blog has at least one entry.

A: 

You can use the latest() method of the related manager:

blogs = Blog.objects.all()

a_blog = blogs[0]
latest_entry = a_blog.entry_set.latest()

# or...
latest_entries = [blog.entry_set.latest() for blog in blogs]

Something like that.

lenin
That would be the ideal way to do it, but unfortunately (unless I'm seriously mistaken) this would generate more queries than there are blogs (one to get the latest entry for each blog). I was thinking maybe there is some smarter way, but I'm starting to believe that there are none.
Deniz Dogan
A: 

There is a roundabout (and very hackish) way to do this. If you don't mind de-normalizing you can add an optional latest_entry field to your Blog model. You can then override Entry.save() to update this field for the corresponding Blog instance every time an Entry instance is created. Alternately you can add a signal to do this.

def save(self, *args, **kwargs):
    if not self.pk: #This object is being created, not updated.
        self.blog.latest_entry = self        
    models.Model.save(self, *args, **kwargs)

Yep, it is not clean. But it will reduce the number of queries. Then you can do:

[(blog, blog.latest_entry) for blog in Blog.objects.all()]
Manoj Govindan