【问题标题】:Django Filter with Pagination带分页的 Django 过滤器
【发布时间】:2018-07-10 20:10:14
【问题描述】:

我正在尝试按照以下教程使用 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 个用户的搜索结果进行分页。我现在得到的是整个用户集。过滤器正常工作,但分页不正常。

【问题讨论】:

  • 您的问题有{% for user in filter.qs %},但您没有在问题的其他任何地方使用filter
  • 这不是在调用我的 filter.py 吗?我在上面插入了 filter.py。我的搜索结果使用 filter.qs 正确地通过我的 for 循环,如果我将其更改为用户,我不会得到任何结果。过滤器应该在 filter.form 上,它显示在模板的顶部。
  • 你不能像那样从模板中调用 python 模块。您的视图有一个上下文{ 'users': users },因此您可以在模板中访问{{ users }}。该视图不会将filter 添加到上下文中,因此{{ filter.qs }} 不会起作用。
  • 好的,我想我明白了。我应该将此添加到我的 def search(request) user_filter = UserFilter(request.GET, queryset=user_list) 然后调用 {'filter': user_filter}
  • 看起来差不多,与the django-filter docs 中的示例非常相似。然后,一旦可行并且您想要对结果进行分页,请尝试将分页器更改为使用 user_filter.qs 而不是 user_listpaginator = Paginator(user_filter.qs, 1)

标签: django django-filter django-pagination


【解决方案1】:

你可以这样分页:

注意: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 %}

【讨论】:

  • 我已经更新了我的代码,但我的分页仍然无法正常工作。我已经更改了我的代码以匹配您的代码,我还包括了我的 filters.py 和目录结构,也许它与此有关。它不适用于 user_list 的搜索结果。
  • 尝试将分页移至 base.html,您是否已将 filter.qs 更改为 users?
  • 我再次更新了我的代码。现在使用 base.html。但是,如果我将 {% for user in filter.qs %} 更改为 {% for user in users %} 我的过滤器将停止运行。
【解决方案2】:

实施步骤

  1. 安装包pip install filter-and-pagination
  2. 通过from filter_and_pagination import FilterPagination在view.py中导入FilterPagination
  3. 在您的函数中按照以下标准编写代码...
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 序列化器类
  1. 在结果集中它包含数据集和分页数据,采用这种格式(API 响应)链接:https://github.com/ashish1997it/filter-pagination-dj#demo
  2. 对于 API 请求,请按照 PostMan 集合链接:https://github.com/ashish1997it/filter-pagination-dj#postman 在标题部分中,它将采用您根据需要自定义的参数和请求

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

【讨论】:

    【解决方案3】:

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

    paginator = Paginator(user_list.qs, 10)
    

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

    paginator = Paginator(user_list, 10) 
    

    即没有 .qs,因为您已经在上一行中使用 user_list = user_filter.qs 定义了 user_list

    【讨论】:

      【解决方案4】:

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

      以下是一些建议:

      1.请尝试Q objects

      2.kwargs可以做很多事情

      3.DjangoREST Framework Filtering

      4.对于类似搜索引擎的功能haystack is a beast - 对于新手来说可能有点复杂。

      5.您也可以使用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>
      

      【讨论】:

      • 有没有可能我需要在我的 settings.py 中包含一些可能丢失的分页?分页永远不会发生,所以它没有给出错误,但可能是这样吗?
      • 由于您使用的是 Django 小部件调整,所以我相信您已经使用 pip install django-widget-tweaks 安装了小部件调整并包含在 INSTALLED_APPS = [ 'widget_tweaks', ] 中,只有其他的事情是 Django 可以找到您的静态文件和模板,并且您的 filters.py 设置正确
      • avails/avail_list.html 的网址是什么样的?我正在使用 return render(request, 'search/search.html', context) 我的项目 url 是 url(r'^search/$', FilterView.as_view(filterset_class=UserFilter, template_name='search/search.html '), name='search'), with url(r'^search/', include('mysite.search.urls')),
      • 这是我的搜索视图url(r'^account/$', views.avail_list, name='avail_list'), 和项目urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('home2.urls')), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 的avail_list 应用程序的网址
      【解决方案5】:

      我现在已经对其进行了测试!对我来说效果很好。只需与 view like the previous answer 共享模板的一部分

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

      【讨论】:

      • 项目的视图是什么?我不认为问题出在我的模板上。
      • 和上一个视图完全一样。
      • 请添加代码而不是使用a view like the previous answer之类的词。
      • 上一个视图是我的应用程序视图。我只是想看看物品的来源。
      【解决方案6】:

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

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

      【讨论】:

      • 这将如何与 Django 过滤器一起使用?我试图实现这一点,它在初始负载上工作,但破坏了我的过滤器。如果我这样做,我无法将这一行 {% for user in filter.qs %} 更改为 {% for obj in object_list %}。
      猜你喜欢
      • 2018-05-11
      • 2019-08-17
      • 2018-06-02
      • 2019-08-14
      • 2017-09-22
      • 2019-02-21
      • 2021-02-28
      • 2015-04-17
      • 2018-02-20
      相关资源
      最近更新 更多