【问题标题】:How to change ordering after updating get_queryset in Django ListView?在 Django ListView 中更新 get_queryset 后如何更改排序?
【发布时间】:2019-10-16 02:04:15
【问题描述】:

我有一个列表视图,在其中实现了搜索栏功能,但我的排序现在似乎不起作用。我该如何解决?我希望能够在 get_queryset 方法之后以我想要的方式订购列表..

class MemoListView(LoginRequiredMixin, ListView):
    model = Memo
    template_name = 'memos/memos.html'
    context_object_name = 'memos'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['memo_list'] = Memo.objects.all()
        return context

    def get_ordering(self):
        ordering = self.request.GET.get('ordering', '-date_time')
        return ordering

    def get_queryset(self):
        query = self.request.GET.get('q')
        if query:
            memo_list = Memo.objects.filter(
                Q(title__icontains=query) | Q(content__icontains=query))
        else:
            memo_list = Memo.objects.all()
        return memo_list

【问题讨论】:

    标签: python django


    【解决方案1】:

    如果您查看 ListView 的源代码,您会看到这样的类。

    class MultipleObjectMixin(ContextMixin):
        """A mixin for views manipulating multiple objects."""
        allow_empty = True
        queryset = None
        model = None
        paginate_by = None
        paginate_orphans = 0
        context_object_name = None
        paginator_class = Paginator
        page_kwarg = 'page'
        ordering = None
    
        def get_queryset(self):
            """
            Return the list of items for this view.
    
            The return value must be an iterable and may be an instance of
        `    QuerySet` in which case `QuerySet` specific behavior will be enabled.
            """
            if self.queryset is not None:
                queryset = self.queryset
                if isinstance(queryset, QuerySet):
                    queryset = queryset.all()
            elif self.model is not None:
                queryset = self.model._default_manager.all()
            else:
                    raise ImproperlyConfigured(
                    "%(cls)s is missing a QuerySet. Define "
                    "%(cls)s.model, %(cls)s.queryset, or override "
                    "%(cls)s.get_queryset()." % {
                        'cls': self.__class__.__name__
                    }
                )
            ordering = self.get_ordering()
            if ordering:
                if isinstance(ordering, str):
                    ordering = (ordering,)
                queryset = queryset.order_by(*ordering)
    
            return queryset
    
        def get_ordering(self):
            """Return the field or fields to use for ordering the queryset."""
            return self.ordering
    

    在您的代码中,您将覆盖 get_ordering() 以提供您想要的排序。但是您还覆盖了调用 get_ordering() 的 get_queryset() 方法。如果您没有覆盖 get_queryset() 方法,您的排序将被默认的 get_queryset() 方法接受。但是由于您要覆盖 get_queryset() 方法,因此您必须明确使用 get_ordering() 方法。

    通过执行类似的操作更改您的 get_queryset()。

    def get_queryset(self):
        query = self.request.GET.get('q')
        if query:
            memo_list = Memo.objects.filter(
                Q(title__icontains=query) | Q(content__icontains=query))
        else:
            memo_list = Memo.objects.all()
        ordering = self.get_ordering()
        memo_list = memo_list.order_by(ordering)
        # The following checks are not needed since your get_ordering() will always only return ONE string
        # if ordering and isinstance(ordering, str):
            # ordering = (ordering,)
            # memo_list = memo_list.order_by(*ordering)
        return memo_list
    

    【讨论】:

    • 我对@9​​87654323@ 感到困惑,传入str 以及为什么(ordering, ) 也是一个元组。
    • isinstance() 用于检查对象的类型。在这种特殊情况下,我检查了 ordering 是否为字符串。关于为什么我传递一个元组,我基本上复制了 django 源代码,所以它不必是一个元组。您可以像这样直接在 order_by() 中使用排序。 ordering = self.get_ordering() memo_list = memo_list.order_by(ordering)
    【解决方案2】:

    您需要调用超级get_queryset函数才能使get_ordering函数生效。

    将此添加到您的 get_queryset() 函数中

    queryset = super(IndexView, self).get_queryset()
    

    【讨论】:

      【解决方案3】:

      或者,您可以将order_by 方法添加到您进行查询的行。所以类的return 行会变成:

      return memo_list.order_by('-date_time')
      

      【讨论】:

        猜你喜欢
        • 2021-08-09
        • 2019-10-25
        • 1970-01-01
        • 2015-12-18
        • 1970-01-01
        • 2019-02-02
        • 1970-01-01
        相关资源
        最近更新 更多