带分页的 Django 过滤器

Django Filter with Pagination

我正在尝试按照以下教程使用 Django 过滤器进行分页,但该教程似乎缺少某些内容,而且我无法使用基于函数的视图方法显示分页。

https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html

My updated users_list.html is the following:

   {% extends 'base.html' %}

{% load widget_tweaks %}

{% block content %}
  <form method="get">
    <div class="well">
      <h4 style="margin-top: 0">Filter</h4>
      <div class="row">
        <div class="form-group col-sm-4 col-md-4">
          <label/> 3-4 User ID
          {% render_field filter.form.employeentname class="form-control" %}
        </div>
        <div class="form-group col-sm-4 col-md-4">
          <label/> First Name
          {% render_field filter.form.employeefirstname class="form-control" %}
        </div>
        <div class="form-group col-sm-4 col-md-4">
          <label/> Last Name
          {% render_field filter.form.employeelastname class="form-control" %}
        </div>

        <div class="form-group col-sm-4 col-md-4">
          <label/> Status
          {% render_field filter.form.statusid class="form-control" %}
        </div>

        <div class="form-group col-sm-4 col-md-4">
          <label/> Title
          {% render_field filter.form.positiondesc class="form-control" %}
        </div>
      </div>
      <button type="submit" class="btn btn-primary">
        <span class="glyphicon glyphicon-search"></span> Search
      </button>
    </div>
  </form>
  <form action = "{% url 'results' %}" form method = "POST">
        {% csrf_token %}
  <table class="table table-bordered">
    {{ form.as_table }}
    <thead>
      <tr>
        <th>3-4</th>
        <th>First name</th>
        <th>Last name</th>
        <th>Title</th>
        <th>Status</th>
        <th></th>

      </tr>
    </thead>
    <tbody>
      {% for user in filter.qs %}
        <tr>
          <td>{{ user.employeentname }}</td>
          <td>{{ user.employeefirstname }}</td>
          <td>{{ user.employeelastname }}</td>
          <td>{{ user.positiondesc }}</td>
          <td>{{ user.statusid }}</td>
          <td><input type="checkbox" name="usercheck" value = "{{user.employeentname}}" />&nbsp;</td>

        </tr>
      {% empty %}
        <tr>
          <td colspan="5">No data</td>
        </tr>
      {% endfor %}
    </tbody>
  </table>



          <button class="btn btn-primary" type="submit">Select User</button>
        </form>
{% endblock %}

我下面的观点是基于教程,但我使用的是我自己的模型:

def user_list(request):
    user_list = Employee.objects.all()
    user_filter = UserFilter(request.GET, queryset=user_list)
    user_list = user_filter.qs
    page = request.GET.get('page', 1)



    paginator = Paginator(user_list.qs, 10)
    try:
        users = paginator.page(page)
    except PageNotAnInteger:
        users = paginator.page(1)
    except EmptyPage:
        users = paginator.page(paginator.num_pages)


    args = {'filter':user_filter, 'users':users}


    return render(request, 'user_list.html', args)

我的目录结构设置如下,也许与此有关:

from django import forms
from .models import Employee

import django_filters


class UserFilter(django_filters.FilterSet):


    class Meta:
        model = Employee
        fields =  ['employeentname', 'employeefirstname', 'employeelastname', 'statusid', 'positiondesc']





    def __init__(self, *args, **kwargs):
        super(UserFilter, self).__init__(*args, **kwargs)
        # at sturtup user doen't push Submit button, and QueryDict (in data) is empty
        if self.data == {}:
            self.queryset = self.queryset.none()

在移动分页后添加了我的 base.html:

{% load static %}<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <style type="text/css">
      .page-header {
        margin-top: 0;
      }
    </style>
  </head>
  <body>
    {% include 'includes/header.html' %}
    <div class="container">
      {% block content %}
      {% if users.has_other_pages %}
        <ul class="pagination">
         {% if users.has_previous %}
           <li><a href="?page={{ users.previous_page_number }}">&laquo;</a></li>
         {% else %}
          <li class="disabled"><span>&laquo;</span></li>
       {% endif %}
         {% for i in users.paginator.page_range %}
           {% if users.number == i %}
             <li class="active"><span>{{ i }} <span class="sr-only">(current)
          </span></span></li>
           {% else %}
             <li><a href="?page={{ i }}">{{ i }}</a></li>
           {% endif %}
         {% endfor %}
         {% if users.has_next %}
           <li><a href="?page={{ users.next_page_number }}">&raquo;</a></li>
         {% else %}
           <li class="disabled"><span>&raquo;</span></li>
         {% endif %}
       </ul>
         {% endif %}
      {% endblock %}
    </div>
    <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>





    {% block javascript %}

    {% endblock %}
  </body>
</html>

我期望我的过滤器为每 10 个用户对搜索结果进行分页。我现在得到的是整个用户集。过滤器工作正常,分页不正常。

我在我的博客上写了一篇 post 关于使用基于函数的视图用 Django 实现分页的文章,你可以查看 here

我已经讨论了在 Django 中实现分页的几种方法

你可以这样分页:

注意:user_filter.qs 有过滤结果,user_filter.queryset 有未过滤结果

views.py

      def search(request):
         user_list = Employee.objects.all()
         user_filter = UserFilter(request.GET, queryset=user_list)
         user_list = user_filter.qs
         
         paginator = Paginator(user_list, 10)
         page = request.GET.get('page', 1)
         try:
            users = paginator.page(page)
         except PageNotAnInteger:
            users = paginator.page(1)
         except EmptyPage:
            users = paginator.page(paginator.num_pages)
         args = {'paginator': paginator,'filter':user_filter, 
           'users':users,}
         return render(request, 'search/user_list.html', args)

然后在模板中:

   {% for user in users %}
     <tr>
      <td>{{ user.employeeusername }}</td>
      <td>{{ user.employeefirstname }}</td>
      <td>{{ user.employeelastname }}</td>
      <td>{{ user.statusid }}</td>
      <td><input type="checkbox" name="usercheck" />&nbsp;</td>

    </tr>
  {% empty %}
    <tr>
      <td colspan="5">No data</td>
    </tr>
  {% endfor %}
</tbody>
 {% if users.has_other_pages %}
   <ul class="pagination">
    {% if users.has_previous %}
      <li><a href="?page={{ users.previous_page_number }}">&laquo;</a></li>
    {% else %}
     <li class="disabled"><span>&laquo;</span></li>
  {% endif %}
    {% for i in users.paginator.page_range %}
      {% if users.number == i %}
        <li class="active"><span>{{ i }} <span class="sr-only">(current)
     </span></span></li>
      {% else %}
        <li><a href="?page={{ i }}">{{ i }}</a></li>
      {% endif %}
    {% endfor %}
    {% if users.has_next %}
      <li><a href="?page={{ users.next_page_number }}">&raquo;</a></li>
    {% else %}
      <li class="disabled"><span>&raquo;</span></li>
    {% endif %}
  </ul>
{% endif %}

我现在已经测试过了!me.Just 与

共享模板的一部分时效果很好
      <div class="row">
        <div class="form-group col-sm-4 col-md-3">

          {{ filter.form.row_date.label_tag }}
          {% render_field filter.form.row_date class="form-control" %}

        </div>

        <div class="form-group col-sm-4 col-md-3">
          {{ filter.form.director.label_tag }}
          {% render_field filter.form.director class="form-control" %}
        </div>
        <div class="form-group col-sm-8 col-md-6">
          {{ filter.form.manager.label_tag }}
          {% render_field filter.form.manager class="form-control" %}
        </div> 
        <div class="form-group col-sm-8 col-md-6">
          {{ filter.form.analyst.label_tag }}
          {% render_field filter.form.analyst class="form-control" %}
        </div> 
        <div class="form-group col-sm-8 col-md-6">
        <button type="submit" class="btn btn-primary">
        <span class="glyphicon glyphicon-search"></span> Search
        </button>
        </div>
        </div>
      </div>

    </div>
  </form>

  <table class="table table-bordered" >
    <thead>
      <tr>

        <th>row_date</th>
        <th>Director</th>
        <th>Manager</th>
        <th>Analyst</th>

      </tr>
    </thead>
    <tbody>
      {% for a in users %}
        <tr>
          <td>{{ a.row_date }}</td>
          <td>{{ a.director }}</td>
          <td>{{ a.manager }}</td>
          <td>{{ a.analyst }}</td>

          <td colspan="5">No data</td>
        </tr>
        {% empty %}
        <tr>
          <td colspan="5">No data</td>
        </tr>
        {% endfor %}
      </tbody>
      </table>
    </div>
       {% block javascript %}
    <script src="{% static 'search/js/jquery-3.1.1.min.js' %}"></script>
    <script src="{% static 'search/js/bootstrap.min.js' %}"></script>

     {% endblock %}
  </body>
</html>

它对我来说很好用。 如果仍然不行,最好节省时间并尝试其他替代方案。

这里有一些建议:

1.Please试试Q objects

2.You 可以用 kwargs 做很多事情

3.Django REST Framework Filtering

4.For search-engine 喜欢的能力 haystack is a beast - 对于新手来说可能有点复杂。

5.You也可以用Elastic Search.

Views.py

def avail_list(request):
        avails1 = AvailstaticCopy.objects.all().order_by('-row_date')
        avail_filter = AvailFilter(request.GET, queryset=avails1)
        avails1 = avail_filter.qs


        paginator = Paginator(avails1, 144)
        page = request.GET.get('page',1)

        try:
            users = paginator.page(page)
        except PageNotAnInteger:
            users = paginator.page(1)
        except EmptyPage:
            users = paginator.page(paginator.num_pages)


        context = {
            'paginator': paginator,
            'users': users,
            'filter': avail_filter,
        }
        return render(request,'avails/avail_list.html',context)

部分模板供参考,情况类似问题:

     <div class="row">
        <div class="form-group col-sm-4 col-md-3">

          {{ filter.form.row_date.label_tag }}
          {% render_field filter.form.row_date class="form-control" %}

        </div>

        <div class="form-group col-sm-4 col-md-3">
          {{ filter.form.director.label_tag }}
          {% render_field filter.form.director class="form-control" %}
        </div>
        <div class="form-group col-sm-8 col-md-6">
          {{ filter.form.manager.label_tag }}
          {% render_field filter.form.manager class="form-control" %}
        </div> 
        <div class="form-group col-sm-8 col-md-6">
          {{ filter.form.analyst.label_tag }}
          {% render_field filter.form.analyst class="form-control" %}
        </div> 
        <div class="form-group col-sm-8 col-md-6">
        <button type="submit" class="btn btn-primary">
        <span class="glyphicon glyphicon-search"></span> Search
        </button>
        </div>
        </div>
      </div>

    </div>


  <table class="table table-bordered" >
    <thead>
      <tr>

        <th>row_date</th>
        <th>Director</th>
        <th>Manager</th>
        <th>Analyst</th>

      </tr>
    </thead>
    <tbody>
      {% for a in users %}
        <tr>
          <td>{{ a.row_date }}</td>
          <td>{{ a.director }}</td>
          <td>{{ a.manager }}</td>
          <td>{{ a.analyst }}</td>
        </tr>
        {% empty %}
        <tr>
          <td colspan="5">No data</td>
        </tr>
        {% endfor %}
      </tbody>
      </table>
    </div>
       {% block javascript %}
    <script src="{% static 'search/js/jquery-3.1.1.min.js' %}"></script>
    <script src="{% static 'search/js/bootstrap.min.js' %}"></script>

     {% endblock %}
  </body>
</html>

我不知道这是否相关,但在我看来问题可能出在您设置分页器的位置。在您看来,您有

paginator = Paginator(user_list.qs, 10)

但如果您仔细查看提供的解决方案,他们建议您应该使用

paginator = Paginator(user_list, 10) 

ie 没有 .qs,因为您已经在前一行中用 user_list = user_filter.qs

定义了 user_list

实施步骤

  1. 通过 pip install filter-and-pagination
  2. 安装包
  3. 通过 from filter_and_pagination import FilterPagination 在 view.py
  4. 中导入 FilterPagination
  5. 在您的函数中按照以下标准编写代码...
queryset = FilterPagination.filter_and_pagination(request, Customer)
serialize_data = CustomerSerializer(queryset['queryset'], many=True).data
resultset = {'dataset': serialize_data, 'pagination': queryset['pagination']}
  • 在这段代码中Customer是Django模型&
  • CustomerSerializer 是一个 DRF 序列化器 class
  1. 在结果集中它包含数据集和分页数据,采用这种格式(API 响应)link:https://github.com/ashish1997it/filter-pagination-dj#demo
  2. 对于 API 请求,请遵循 PostMan collection link: https://github.com/ashish1997it/filter-pagination-dj#postman 在 header 部分,它将采用一个参数并请求您根据您的要求

如果您仍然遇到任何困难,请与我联系:)