按另一个查询集中的字段对查询集进行排序



在我的django博客应用程序中,我有一个Bookmark模型,其中包括指向Post和User的字段,以及创建书签时的字段。

# models
class Post(models.Model):
# ...
title = models.CharField(max_length=70)
body = RichTextField()
author = models.ForeignKey(
UserProfile,
on_delete=models.CASCADE,
related_name='posts')
created_on = models.DateTimeField(default=timezone.now)
# ...
class Meta:
ordering = ['created_on']

class Bookmark(models.Model):
post = models.ForeignKey(
Post, on_delete=CASCADE,
related_name="bookmarked_post"
)
user = models.ForeignKey(
User, on_delete=CASCADE,
related_name="bookmarks"
)
created_on = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['created_on']

我有一个显示用户书签的视图。我想按照添加书签的顺序对查询集中的帖子进行排序,首先是最近添加书签的帖子。

# views.py
@login_required
def bookmarks_view(request):
bookmarks = Bookmark.objects.filter(user=request.user)
bookmarked_posts = Post.objects.filter(
bookmarked_post__in=bookmarks).order_by(???)
return render(request, 'bookmarks.html', {'posts': bookmarked_posts})

我很难弄清楚如何通过Bookmark模型中的created_on字段对Posts查询集进行排序。为了增加额外的复杂性,Post和Bookmark模型都有一个created_on字段。

有人能为我指出正确的方向吗?我搜索了django文档和SO,没有找到我需要的东西,可能我只是不知道正确的关键词。。。或者我是否错误地设置了我的模型以实现我想要的目标?

这样的东西应该可以工作:

bookmarks = Bookmark.objects.filter(user=u0)
bookmarked_posts = Post.objects.filter(
bookmarked_post__in=bookmarks
).order_by("-bookmarked_post__created_on")

您可以将__created_on放在最后——Django将使用在相关模型上指定的默认ordering。开头的-表示递减,因此较新的日期优先。

另请参阅order_by:的文档

若要按不同模型中的字段排序,请使用与跨模型关系查询时相同的语法。也就是说,字段名称,后跟双下划线(__(,后跟新模型中字段的名称,对于要加入的任意多个模型,依此类推。

因为您将相关名称指定为bookmarked_post,所以从Post的角度来看,这也是您需要指定的字段的名称,就像您在filter中使用它一样。

如果没有related_name,它看起来是这样的:

bookmarks = Bookmark.objects.filter(user=u0)
bookmarked_posts = Post.objects.filter(
bookmark__in=bookmarks
).order_by("-bookmark__created_on")

(请注意,您可能需要在Bookmark模型上为postuser指定unique_together约束,以确保每个用户只能为帖子添加一次书签(

最新更新