Django 1.X和2.0下利用自带分页Paginator类实现分页功能

Django作为Python Web开发框架的一哥,提供了企业级网站开发所需要的几乎所有功能,其中就包括自带分页功能。利用Django自带的Paginator类,我们可以很轻松地实现分页。Django 2.0和1.X最大的不同在于新增了get_page()方法。我们现在来具体看看有什么不同。


Django 1.X 和Django 2.0下实现分页


利用Django实现分类非常简单,我们只需要修改views.py和模板template。Django 1.X下实现分页代码如下:


# app/views.py - 基于函数的视图

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Article
from django.shortcuts import render

def article_list(request): article_list = Article.objects.all() paginator = Paginator(article_list, 10) # 实例化一个分页对象, 每页显示10个 page = request.GET.get('page') # 从URL通过get页码,如?page=3 try: articles = paginator.page(page) # 获取某页对应的记录 except PageNotAnInteger: # 如果页码不是个整数 articles = paginator.page(1) # 提取第一页的记录 except EmptyPage: # 如果页码太大,没有相应的记录 articles = paginator.page(paginator.num_pages) # 提取最后一页的记录 return render(request, 'article_list.html', {'articles': articles})


你注意到没有?上段代码的try和2个except非常重要,但是看上去有些冗余。Django 2.0下新增了get_page()方法,可以将代码大大简化(如下图所示)。它所实现的功能与上面是一样的。当用户提交的页码不是整数时,提取第一页记录。当用户输入的页码太大时,只提取最后一页记录。

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Article
from django.shortcuts import render

def article_list(request): article_list = Article.objects.all() paginator = Paginator(article_list, 10) # 实例化一个分页对象, 每页显示10个 page = request.GET.get('page') # 从URL通过get页码,如?page=3
  articles = paginator.get_page(page) # 获取某页对应的记录, 如果 return render(request, 'article_list.html', {'articles': articles})


Django 1.X和2.0下的模板是一样的。这里提供两种显示方案。

模板一: 上一页, Page 1 of 3, 下一页

#app/templates/app/article_list.html

{% for article in articles %} 
   {{ article.title }}  
{% endfor %}

<div class="pagination">
   <span
class="step-links">
       
{% if articles.has_previous %}
           <a href="?page=1">&laquo; first</a>
           <a
href="?page={{ articles.previous_page_number }}">previous</a>
       
{% endif %}

       <span class="current">
           
Page {{ articles.number }} of {{ articles.paginator.num_pages }}.
       </span>

       
{% if articles.has_next %}
           <a href="?page={{ articles.next_page_number }}">next</a>
           <a
href="?page={{ articles.paginator.num_pages }}">last &raquo;</a>
       
{% endif %}
   </span>
</div>


模板二: Page 1, 2, 3, 4, 5, 6, 7, 8, ... (推荐)

#app/templates/app/article_list.html

# Pagination style 2
{% for article in articles %}
   {{ article.title }}
{% endfor %}
<div class="pagination">
<nav>
   <ul
class="pagination">
       
{% if articles.has_previous %}
       <li class="">
       <a
href="?page={{ articles.previous_page_number }}" aria-label="Previous">
       <span
aria_hidden="true">&laquo;</span></a>
       </li>
       
{% endif %}
       
       {% for page_num in articles.paginator.page_range %}
           {% if page_num == articles.number %}
        <li class="active"><a href="?page={{ page_num }}">{{page_num}}</a> </li>
           
{% else %}
        <li class=""><a href="?page={{ page_num }}">{{page_num}}</a> </li>
           
{% endif %}
       {% endfor %}
       
       {% if articles.has_next %}
        <li class="">
             <a
href="?page={{ articles.next_page_number }}" aria-label="Next">
                 <span
aria_hidden="true">&raquo;</span></a>
       </li>
     
{% endif %}
   </ul>
</nav>
</div>


Django如何在基于类的视图里使用分页?


上述案例里我们使用了函数试图,很容易定义page对象, 并传递给模板,例如articles。但是如果我们希望使用基于类的视图,我们该如何实现分页呢?其实操作非常简单。我们只需在视图中加入paginate_by = number即可。

from. models import Article
from django.views.generic import ListView

class ArticleListView(ListView):
   model = Article  # 等于 queryset = models.Article.objects.all()
   
template_name = 'app/article_list.html'  # 可选的
   
context_object_name = "article_list"    # 默认context名字
   
paginate_by = 10  # 每页10项


此时模板article_list.html也需要做出相应调整,如下图所示。Django会先对是否分页is_paginated做个判断,如果有,就会自动生成个page_obj分页对象传递到模板。

{% if article_list %}
   {% for article in article_list %}
   {{ article.title }}
   {% endfor %}

   {% if is_paginated %}
   <ul class="pagination">
   
{% if page_obj.has_previous %}
   <li>
       <span><a
href="?page={{ page_obj.previous_page_number }}">Previous</a></span>
   </li>
   
{% endif %}
   <li class="">
       <span>
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
   </li>
   
{% if page_obj.has_next %}
<li>
       <span><a
href="?page={{ page_obj.next_page_number }}">Next</a></span>
   </li>
   
{% endif %}
   </ul>

{% else %}
   <h3>Articles</h3>
   <p>
No article yet</p>
{% endif %}


本文【Python与Django大咖之路】原创,如果喜欢我的文章,欢迎关注我的微信公众号。


猜你喜欢

转载自blog.csdn.net/weixin_42134789/article/details/80222585