You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django ListView中通过外键筛选用户关联Blog并排序?

问题描述

我有如下三个Django模型:

  1. Blog模型:
class Blog(models.Model):
    title = models.CharField()
    published = models.DateField()
    ...
  1. AuthorList模型:
class AuthorList(models.Model):
    blog = models.ForeignKey(Blog)
    author = models.ForeignKey(User)
    lastTimeEdited = models.DateTimeField()
    ...
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:25:17