【问题标题】:How to filter and paginate in ListView Django如何在 ListView Django 中过滤和分页
【发布时间】:2020-10-31 05:10:34
【问题描述】:

当我想对使用 django_filter 创建的过滤器进行分页时遇到问题,在我的模板中它向我显示了查询集和过滤器,但分页不起作用,我想知道为什么会发生这种情况,如果你能帮忙我。

我将插入我的代码的 sn-ps 以便您查看。

这是我的观点.py

PD:我有所有必要的进口。

@method_decorator(staff_member_required, name='dispatch')
class EmployeeListView(ListView):
    model = Employee
    paginate_by = 4

    def dispatch(self, request, *args, **kwargs):
        if not request.user.has_perm('employee.view_employee'):
            return redirect(reverse_lazy('home'))
        return super(EmployeeListView, self).dispatch(request, *args, **kwargs)
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = EmployeeFilter(self.request.GET, queryset = self.get_queryset())
        return context

filters.py

import django_filters
from .models import Employee, Accident

class EmployeeFilter(django_filters.FilterSet):

    class Meta:
        model = Employee
        fields = {
            'rutEmployee' : ['startswith']
        }

【问题讨论】:

    标签: python django listview django-class-based-views django-filter


    【解决方案1】:

    您应该覆盖get_queryset。这意味着您必须将过滤器放入get_queryset,如下所示:

    @method_decorator(staff_member_required, name='dispatch')
    class EmployeeListView(ListView):
        model = Employee
        paginate_by = 4
    
        def dispatch(self, request, *args, **kwargs):
            if not request.user.has_perm('employee.view_employee'):
                return redirect(reverse_lazy('home'))
            return super(EmployeeListView, self).dispatch(request, *args, **kwargs)
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['filter'] = EmployeeFilter(self.request.GET, queryset = self.get_queryset())
            return context
        
        def get_queryset(self):
            queryset = super().get_queryset()
            return EmployeeFilter(self.request.GET, queryset=queryset).qs
    

    并在 employee_list.html 中使用 object_list 而不是 filter,如下所示:

    {% for employee in object_list|dictsort:"id" reversed %}
    

    【讨论】:

    • 您好,感谢您的帮助,应用您建议的更改,但它给了我以下错误: TypeError at /employee/ filter_queryset() got multiple values for argument 'queryset' in this line: return EmployeeFilter( ).filter_queryset(self.request.GET, queryset=queryset)
    • 嗨,我刚刚应用了更改,它向我抛出了以下内容:filter_queryset() 接受 2 个位置参数,但给出了 4 个
    • 我以为你使用了休息过滤器。对不起这个错误。请使用新更改重试
    • 如果您在github.com/django/django/blob/master/django/views/generic/… 中看到MultipleObjectMixin 的get_context_data 方法,您就知道查询集是如何分页的。每次使用ListView时,object_list就是分页查询集,所以如果通过覆盖get_queryset来过滤queryset,object_list也会被过滤掉。
    • 这个答案对于弄清楚如何结合FilterView和ListView来说就像金子一样。谢谢
    【解决方案2】:

    你也可以试试这个: (我的源代码中的一个 sn-p)

    class ModelListView(ListView):
        model = YourModel
        paginate_by = 4 # Change this if you don't intend to paginate by 4
        ordering = model_field_to_order_by
        # variable used to know if a match was found for the search made using django_filters
        no_search_result = False
    
        def get_queryset(self, **kwargs):
            search_results = YourDjangoFiltersForm(self.request.GET, self.queryset)
            self.no_search_result = True if not search_results.qs else False
            # Returns the default queryset if an empty queryset is returned by the django_filters
            # You could as well return just the search result's queryset if you want to
            return search_results.qs.distinct() or self.model.objects.all()
    
        def get_query_string(self):
            query_string = self.request.META.get("QUERY_STRING", "")
            # Get all queries excluding pages from the request's meta
            validated_query_string = "&".join([x for x in re.findall(
                r"(\w*=\w{1,})", query_string) if not "page=" in x])
            # Avoid passing the query path to template if no search result is found using the previous query
            return "&" + validated_query_string.lower() if (validated_query_string and not self.no_search_result) else ""
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # Pass to template if you want to do something whenever an empty queryset is return by django_filters
            context["no_search_result"] = self.no_search_result
            # This is the query string which should be appended to the current page in your template for pagination, very critical
            context["query_string"] = self.get_query_string()
            context['filter'] = YourDjangoFiltersForm()
            return context
    
    

    在您的 html 模板中,您需要附加从视图传递给您的模板的查询字符串,示例如下所示

    {% for i in page_obj.paginator.page_range %}
        {% if page_obj.number == i %}
              <li class="page-item active" aria-current="page">
                <span class="page-link">{{ i }}<span class="sr-only">(current)</span></span>
              </li>
              {% elif i > page_obj.number|add:'-5' and i < page_obj.number|add:'5' %} <li class="page-item"><a
                  class="page-link" href="?page={{ i }}{{ query_string }}">{{ i }}</a></li>
        {% endif %}
    {% endfor %}
    
    

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 2019-08-21
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 2018-05-11
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多