如何在Django ListView中通过外键筛选用户关联Blog并排序?
问题描述
我有如下三个Django模型:
- Blog模型:
class Blog(models.Model): title = models.CharField() published = models.DateField() ...
- AuthorList模型:
class AuthorList(models.Model): blog = models.ForeignKey(Blog) author = models.ForeignKey(User) lastTimeEdited = models.DateTimeField() ...
- CommentsList模型:
class CommentsList(models.Model): blog = models.ForeignKey(Blog) commentAuthor = models.ForeignKey(User) commentPosted = models.DateTimeField() ...
我的类基ListView代码如下:
class DashboardView(LoginRequiredMixin, ListView): model = Blog template_name = 'app/dashboard.html' paginate_by = 5 def get_queryset(self) -> QuerySet[Blog]: user = self.request.user author = #HERE I want a queryset of all blogs, where the requested user is one of the authors. commentator = #HERE I want a queryset of all blogs, where the requested user is one of the commentators. blogs = author|commentator return blogs.order_by(#HERE I want to order them by the lastTimeEdited-Field or the commentPosted-Field)
需求:列出所有与当前用户有关联的Blog对象,排序规则为:若用户是该博客的作者,则按lastTimeEdited字段排序;若用户是该博客的评论者,则按commentPosted字段排序。
解决方案
核心思路
直接合并两个查询集后无法用不同字段排序,必须给每个博客标注统一的排序时间字段,区分用户作为作者/评论者的时间来源,再基于这个统一字段排序。
最终代码实现
from django.db.models import Case, When, Max, DateTimeField from django.db.models import Q class DashboardView(LoginRequiredMixin, ListView): model = Blog template_name = 'app/dashboard.html' paginate_by = 5 def get_queryset(self) -> QuerySet[Blog]: user = self.request.user # 筛选所有关联当前用户的博客,并标注排序时间 return Blog.objects.filter( # 条件:用户是作者 或 用户是评论者 Q(authorlist__author=user) | Q(commentslist__commentAuthor=user) ).annotate( sort_time=Case( # 优先取作者的最新编辑时间(一个博客可能有多个作者,取最新的编辑记录) When(authorlist__author=user, then=Max('authorlist__lastTimeEdited')), # 否则取评论者的最新评论时间(同理取最新的评论记录) default=Max('commentslist__commentPosted'), output_field=DateTimeField() ) ).distinct().order_by('-sort_time')
补充说明
distinct()用来去重,避免同一博客因用户既是作者又是评论者而重复出现- 如果需要保留重复条目(比如同一博客分别以作者、评论者身份展示),可以去掉
distinct() - 使用
Max()是因为单篇博客可能对应多条作者编辑记录或评论记录,取最新的时间更符合“最近互动”的排序逻辑
内容的提问来源于stack exchange,提问作者mr.xy
相关产品推荐
相关产品推荐

