如何在 ListView Django 中进行过滤和分页

How to filter and paginate in ListView Django

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

我将插入我的代码片段以便您查看。

这是我的views.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']
        }

您应该覆盖 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 %}

你也可以试试这个: (我的源代码片段)

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 %}