django提供了分页功能接口,比自己用切片来实现方便很多。
利用django的Paginator分页类,加上booststrap美化前端,实现分页功能。
目标效果如下:

  • a) 只显示n个标签页,如5。
    b) 选中变色。
    c) 上一页下一页功能。
    d) 若当前选中第一页,则不再显示上一页标签。
    e) 若当前选中最后页,则不再显示下一页。

图例
django 分页与美化
django 分页与美化

Pagination reffer:https://docs.djangoproject.com/en/1.11/topics/pagination/
主要功能测试
django 分页与美化

PART1: 核心功能实现

-

1.1 django代码

1.1.1 models.py

from django.db import models

class Articles(models.Model):
    title=models.CharField(max_length=32)
    content=models.TextField()

    def __str__(self):
        return self.title

1.1.2 创建测试数据

from  projectname.wsgi import  *
from app01.models import *

for i in range(1,96):
    title="title"+str(i)
    content="text"+str(i)
    Articles.objects.create(title=title,content=content)

django 分页与美化

1.1.3 views.py

from django.shortcuts import render,HttpResponse,redirect
from .models import Articles
from django.core.paginator import Paginator

def page_demo(request):
    articles=Articles.objects.all()
    paginator_obj=Paginator(articles,5) #每页5条
    # print(paginator_obj.page_range)

    request_page_num=request.GET.get('page',1)
    # print(request_page_num)
    page_obj=paginator_obj.page(request_page_num)

    total_page_number=paginator_obj.num_pages

    return render(request,'page_demo.html',{'page_obj':page_obj,'paginator_obj':paginator_obj})

1.1.4 url.py

from django.conf.urls import url,include
from django.contrib import admin
from app01 import  views

urlpatterns = [
    url(r'^page_demo/', views.page_demo),
]

1.2 前端代码

1.2.1 page_demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% for article in page_obj %}
    <div>## {{ article.title }} ##</div>
    <div>{{ article.content }}</div>
{% endfor %}

{% for page_num in paginator_obj.page_range %}
        <a href="?page={{ page_num }}">{{ page_num }}</a>
{% endfor %}

</body>
</html>

小tip: 页数列表paginator_obj.page_range 也可替换成page_obj.paginator.page_range 即由当前页obj关联。views函数可以不再向前端传递paginator_obj

1.2.1 页面

django 分页与美化

翻页

django 分页与美化

以上,功能已经实现,比较丑陋。下面进行页面美化和功能优化。

PART2 页面美化和功能优化

-

2.1 分页标签,显示5页

先写个分页标签显示功能,设定标签数,WEB_DISPLAY_PAGE值。
观察某搜索网站,当显示偶数页10页时,当前页前为5页,当前页后为4页。
django 分页与美化

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# info: edit by infaaf
# blog: https://blog.51cto.com/13606158

def get_pages(totalpage=1,current_page=1):
    """
    example: get_pages(10,1) result=[1,2,3,4,5]
    example: get_pages(10,9) result=[6,7,8,9,10]
    页码个数由WEB_DISPLAY_PAGE设定
    """
    WEB_DISPLAY_PAGE = 5
    front_offset = int(WEB_DISPLAY_PAGE / 2)
    if WEB_DISPLAY_PAGE % 2 == 1:
        behind_offset=front_offset
    else:
        behind_offset=front_offset -1

    if totalpage < WEB_DISPLAY_PAGE:
        return list(range(1,totalpage+1))
    elif current_page<=front_offset:
        return list(range(1,WEB_DISPLAY_PAGE+1))
    elif current_page>=totalpage-behind_offset:
        start_page=totalpage-WEB_DISPLAY_PAGE+1
        return list(range(start_page,totalpage+1))
    else:
        start_page=current_page-front_offset
        end_page=current_page+behind_offset
        return list(range(start_page,end_page+1))

if __name__ == '__main__':
    res=get_pages(10,1)
    print(res)

2.2 views.py改写

from django.shortcuts import render,HttpResponse,redirect
from .models import Articles
from django.core.paginator import Paginator
# Create your views here.
from app01.mylib.paginator_disp_nums import get_pages

def page_demo(request):
    articles=Articles.objects.all()
    paginator_obj=Paginator(articles,5) #每页5条
    # print(paginator_obj.page_range)

    request_page_num=request.GET.get('page',1)
    # print(request_page_num)
    page_obj=paginator_obj.page(request_page_num)

    total_page_number=paginator_obj.num_pages
    print(total_page_number)
    page_list=get_pages(int(total_page_number),int(request_page_num))

    return render(request,'page_demo.html',{'page_obj':page_obj,'page_list':page_list})

2.3 前端页面中,分页部分加入bootstrap美化。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<link rel="stylesheet" href="/static/plugin/bootstrap-3.3.7/css/bootstrap.css">

<body>
{% for article in page_obj %}
    <div>## {{ article.title }} ##</div>
    <div>{{ article.content }}</div>
{% endfor %}

<nav aria-label="Page navigation">
  <ul class="pagination">

    {% if  page_obj.previous_page_number > 0 %}
    <li>
      <a href="?page={{ page_obj.previous_page_number}}" aria-label="Previous">
        <span aria-hidden="true">«</span>
      </a>
    </li>
    {% endif %}

    {% for page_num in page_list %}
            {% if page_num == page_obj.number %}
                <li class="active"><a href="?page={{ page_num }}">{{ page_num }}</a></li>
            {% else %}
                <li><a href="?page={{ page_num }}">{{ page_num }}</a></li>
            {% endif %}
    {% endfor %}

    {% if page_obj.has_next %}
    <li>
      <a href="?page={{ page_obj.next_page_number }}" aria-label="Next">
        <span aria-hidden="true">»</span>
      </a>
    </li>
    {% endif %}

  </ul>
</nav>

<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/plugin/bootstrap-3.3.7/js/bootstrap.js"></script>

</body>
</html>

完成,按页次获取不同内容,页面标签显示。
django 分页与美化

django 分页与美化

django 分页与美化

part3 更好的方式

自定义类,python django提供的Paginator欠缺以上标签页范围等,自己实现个差不多功能的。
有需要功能,再添加即可,方便扩展。

工具类

#/usr/bin/env python3
# author infaaf 
# 20180314

class Paginator:
    def __init__(self,obj_count=1,obj_perpage=1,pagetag_current=1,pagetag_dsp_count=1):
        '''
        :param obj_count: 获得 条目总数
        :param obj_perpage: 定义 每页显示条目数
        :param pagetag_current: 获得 当前页码
        :param pagetag_dsp_count: 定义 显示多少个页码
        '''
        self.obj_count=obj_count
        self.obj_perpage=obj_perpage

        try:
            pagetag_current=int(pagetag_current)
            if pagetag_current < 1:
                pagetag_current=1
            self.pagetag_current=pagetag_current
        except Exception as e:
            self.pagetag_current=1

        self.pagetag_dsp_count=pagetag_dsp_count
        self.pagetag_all_count=self.last_page

    @property
    def obj_slice_start(self):
        return (self.pagetag_current-1)*self.obj_perpage

    @property
    def obj_slice_end(self):
        return self.pagetag_current* self.obj_perpage

    @property
    def has_prev_page(self):
        return False if self.pagetag_current <= self.first_page else True

    @property
    def has_next_page(self):
        return False if self.pagetag_current >= self.last_page else True

    @property
    def prev_page(self):
        if self.pagetag_current==1:
            return 1
        elif self.pagetag_current > self.pagetag_all_count:
            return self.pagetag_all_count
        else:
            return self.pagetag_current-1

    @property
    def next_page(self):
        if self.pagetag_current >= self.pagetag_all_count:
            return self.pagetag_all_count
        else:
            return self.pagetag_current+1

    @property
    def first_page(self):
        return 1

    @property
    def last_page(self):
        if self.obj_count % self.obj_perpage == 0:
            pagecount=int(self.obj_count / self.obj_perpage)
        else:
            pagecount = int(self.obj_count / self.obj_perpage)+1
        return pagecount

    @property
    def pagetag_range(self):
        '''页码列表'''
        start=1
        end=1
        #pagetag页码数 奇数偶数情况下,前后多少个不同。
        if self.pagetag_dsp_count%2==1:
            before=int(self.pagetag_dsp_count/2)
            after=before
        else:
            before=int(self.pagetag_dsp_count/2)
            after=before-1

        if self.pagetag_all_count < self.pagetag_dsp_count:
            start=1
            end=self.pagetag_all_count+1
        elif self.pagetag_current <= before:  #当前页码过小时
            start=1
            end=self.pagetag_dsp_count+1
        elif self.pagetag_current >= self.pagetag_all_count - after: #当前页码过大时
            start=self.pagetag_all_count - self.pagetag_dsp_count +1
            end=self.pagetag_all_count+1
        else:
            start=self.pagetag_current - before
            end=self.pagetag_current + after +1
            # print("logging %s %s %s"%(self.pagetag_current,self.pagetag_dsp_count,self.pagetag_dsp_count))

        return range(start, end)

view

from django.shortcuts import render

# Create your views here.
from .lib.paginator import Paginator
art_list=[]
for i in range(1,200):
    a="art_"+str(i)
    art_list.append(a)

        # '''
        # :param obj_count: 获得 条目总数
        # :param obj_perpage: 定义 每页显示条目数
        # :param pagetag_current: 获得 当前页码
        # :param pagetag_dsp_count: 定义 显示多少个页码
        # '''

def pag(request):
    obj_count=len(art_list)
    obj_perpage=10
    pagetag_current=request.GET.get('page',1)
    pagetag_dsp_count=6
    paginator=Paginator(obj_count,obj_perpage,pagetag_current,pagetag_dsp_count)

    art_obj=art_list[paginator.obj_slice_start:paginator.obj_slice_end]

    return render(request,'pag.html',{'art_obj':art_obj,'paginator':paginator})

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
</head>
<body>
{% load admin_urls %}
    {% for obj in art_obj %}
        {{ obj }}
    {% endfor %}

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
        {% if paginator.has_prev_page %}
      <a href="{% url 'pag' %}?page={{ paginator.first_page }}" aria-label="Previous">
        <span aria-hidden="true">首页</span>
      </a>
        {% endif %}
    </li>

    <li>
        {% if paginator.has_prev_page %}
      <a href="{% url 'pag' %}?page={{ paginator.prev_page }}" aria-label="Previous">
        <span aria-hidden="true">«</span>
      </a>
        {% endif %}
    </li>

    {% for pagenum in paginator.pagetag_range %}
        {% if paginator.pagetag_current == pagenum %}
            <li class="active"><a href="{% url 'pag' %}?page={{ pagenum }}">{{ pagenum }}</a></li>
            {% else %}
            <li><a href="{% url 'pag' %}?page={{ pagenum }}">{{ pagenum }}</a></li>
        {% endif %}
    {% endfor %}

    <li>
        {% if paginator.has_next_page %}
      <a href="{% url 'pag' %}?page={{ paginator.next_page }}" aria-label="Next">
        <span aria-hidden="true">»</span>
      </a>
        {% endif %}
    </li>

    <li>
        {% if paginator.has_next_page %}
      <a href="{% url 'pag' %}?page={{ paginator.last_page }}" aria-label="Next">
        <span aria-hidden="true">尾页</span>
      </a>
        {% endif %}
    </li>

  </ul>
</nav>

    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7/js/bootstrap.js"></script>
</body>
</html>