Django: query latest posts from different categories
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, 开发者_C百科for example. Is it possible?
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.
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.
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/
Using order_by and distinct:
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.
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
精彩评论