使用 get_queryset 对列表视图进行排序

Aur*_*ien 4 django django-orm

两种模型:帖子和作者
此视图显示每个作者的最后一篇帖子(作者是外键)

我想按降序排列这些帖子,但这不起作用。模板继续以升序方式显示这些内容。
我尝试以下操作:

视图.py

class LastestListView(ListView):
    context_object_name = 'posts'
    model = models.Post
    ordering = ['-date']
    paginate_by = 10

    def get_queryset(self):
        return self.model.objects.filter(pk__in=
        Post.objects.values('author__id').annotate(
            max_id=Max('id')).values('max_id'))
Run Code Online (Sandbox Code Playgroud)

或者:

class LastestListView(ListView):
    context_object_name = 'posts'
    model = models.Post
    paginate_by = 10

    def get_queryset(self):
        return self.model.objects.filter(pk__in=
        Post.objects.order_by('-date').values('author__id').annotate(
            max_id=Max('id')).values('max_id'))
Run Code Online (Sandbox Code Playgroud)

解决方案

必须在查询集的开头设置顺序:

class LastestListView(ListView):
    context_object_name = 'posts'
    model = models.Post
    paginate_by = 10

    def get_queryset(self):
        return self.model.objects.order_by('-date').filter(pk__in=
        Post.objects.values('author__id').annotate(
            max_id=Max('id')).values('max_id'))
Run Code Online (Sandbox Code Playgroud)

hyn*_*cer 5

更准确地说,排序应该应用于主查询,而不是子查询。

我更喜欢过滤后的排序,这只是一个意见问题。

def get_queryset(self):
    qs = (
        self.model.objects
        .filter(
            pk__in=(
                Post.objects
                .values('author_id')
                .annotate(max_id=Max('id'))
                .values('max_id')
            )
        )
        .order_by('-date')
    )
    # print(str(qs.query))   # SQL check is perfect for debugging
    return qs
Run Code Online (Sandbox Code Playgroud)

也许这种更稀疏的风格和严格的缩进有助于编写易于阅读的代码。优点是您可以更轻松地注释掉方法或通过更改行的顺序来更改方法的顺序。您还可以清楚地看到 是order_by在主查询还是子查询中。