Reputation: 1034
class Post(models.Model):
title = ...
category = models.ForeignKey(Category)
date = .......
class Category(models.Model):
title = ....
On the main page i want to display 5 posts with latest dates, but all posts must be from different categories. There is 50 categoriese, for example. Is it possible?
Upvotes: 1
Views: 2845
Reputation: 10680
Post.objects.all().order_by('category', 'date').distinct('category')
Then for performance adding index together on category
and date
fields.
But i think real production way is to use Redis
to cache and update an id's list of latest posts of categories.
Upvotes: 1
Reputation: 1678
You bet it's possible.
Randomly select 5 categories
Grab the most recent post for each category
Perhaps something like:
randposts = {} #list for most recent posts of 5 randomly selected categories
for randomcat in Category.objects.order_by('?')[5:]:
randposts.add(Post.objects.filter(category = randomcat).order_by('date')[0])
This may help: https://docs.djangoproject.com/en/dev/ref/models/querysets/
Upvotes: 1
Reputation: 239360
from django.db.models import Max
categories = Category.objects.annotate(most_recent=Max(post__date)).order_by('-most_recent')[:5]
posts = list()
for category in categories:
posts.append(category.post_set.latest())
That annotates the categories with the date of the most recent post as the value of most_recent
, which you can then order by to get the 5 most recent categories.
Then, just loop through the categories and pull out the latest post for each. Done.
Upvotes: 6
Reputation: 377
Cleaned up version of Doc's code:
catsused = {}
posts = {}
for post in Post.objects.order_by('date'):
if post.category not in catsused:
posts.add(post)
catsused.add(post.category)
if len(catsused) == 5:
break
Upvotes: 0
Reputation: 1678
Okay, let's try this again..
catsused = {}
posts = {}
postindex = 0
posts.add(Post.objects.order_by('date')[postindex])
catsused.add(Post.objects.order_by('date')[postindex].category
for each in range(1,5):
postindex = postindex + 1
post = Post.objects.order_by('date')[postindex]
while post.category in catsused:
postindex = postindex + 1
post = Post.objects.order_by('date')[postindex]
posts.add(post)
catsused.add(post.category)
posts ## Now contains your posts
That seems like horrible code to me, but I suppose something close to that will do the job. You'll wanna add some code to handle "postindex" going over the number of posts there are in the system too.
Upvotes: 1