django模型系统综合案例-分页(手动分页、内置分页)

完成结果如下:

django模型系统综合案例-分页(手动分页、内置分页)

1.手动分页

视图view.py修改成如下:

def students(request):
    section = '学生列表'
    #获取查询参数
    search = request.GET.get('search','').strip()

    if search:
        if search.isdigit():
            sts = Student.objects.filter(Q(qq=search)|Q(phone=search),is_deleted=False).order_by('-e_time')
            #是qq或者电话
        else:
            sts = Student.objects.filter(name__contains=search,is_deleted=False).order_by('-e_time')
    else:
        sts = Student.objects.filter(is_deleted=False).order_by('-e_time')
   #当前页
    page = request.GET.get('page',1)
    page = int(page)
    #每页显示多少数据
    per_page = request.GET.get('per_page',10)
    per_page = int(per_page)
    total_num = sts.count()  #总学生数
    sts = sts[(page-1)*per_page:page*per_page]
    return render(request,'teacher/students.html',context=
    {'students':sts,
     'section':section,
     'search':search,
     'per_page':per_page,
     'page':page,
     'total_num':total_num
     })

students.html修改如下:(只显示了修改部分的代码)

....
{% load customer_tags %} #引用自定义的标签
.... </div> <div class="btn-group" role="group"> <div class="btn-group" role="group"> <nav aria-label="Page navigation"> {% pagination_html %} </nav> </div> <div class="btn-group" role="group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ per_page }}条/页<span class="caret"></span> </button> <ul class="dropdown-menu"> <li><a href="{{ request.path }}?search={{ search }}&per_page=5">5条/页</a></li> <li><a href="{{ request.path }}?search={{ search }}&per_page=10">10条/页</a></li> <li><a href="{{ request.path }}?search={{ search }}&per_page=20">20条/页</a></li> </ul> </div>

自定义标签customer_tag.py

@register.inclusion_tag('teacher/pagination.html',takes_context=True) #takes_context=True 能够取到在views中所有的context的上下文
def pagination_html(context):
    num = 3  #总共显示多少个页码
    page_num = context['page']
    per_page = context['per_page']
    students = context['students']
    #总学生数
    total_num = context['total_num']
    #总页数
    total_page = math.ceil(total_num/per_page)
    #页码列表
    page_list=[]
    #生成当前页,以及左边的页数
    if page_num - (num-1)//2 <=0: #说明左边的页数应该从1开始
        for i in range(page_num):
            page_list.append(i+1)
    else: #左边的页数应该从 page_num -(num-1)//2开始
        for i in range(page_num-(num-1)//2,page_num+1):
            page_list.append(i)

     #生成右边的页数
    if page_num + (num-1)//2 >= total_page:
        for i in range(page_num+1,total_page+1):
            page_list.append(i)
    else:
        for i in range(page_num+1,page_num+(num-1)//2+1):
            page_list.append(i)

    return {
        'page_num_list':page_list,
        'page_num':page_num,
        'context':context,
        'total_page':total_page
    }

自定义标签中需要渲染的页面

 <ul class="pagination" style="margin: 0px">
    <li {% if page_num == 1 %}class="disabled" {% endif %}>
      <a href="{{ request.path }}?search = {{ context.search }}&page={{ page_num|add:'-1' }}&per_page={{ context.per_page }}" aria-label="Previous">
        <span aria-hidden="true">上一页</span>
      </a>
    </li>
    {% for num in page_num_list %}
    <li {% if num == page_num %}class="active"{% endif %}><a href="{{ request.path }}?search={{ context.search }}&page={{ num }}&per_page={{ context.per_page }}">{{ num }}</a></li>
     {% endfor %}
    <li {% if page_num == total_page %}class="disabled" {% endif %}>

      <a href="{{ request.path }}?search = {{ context.search }}&page={{ page_num|add:'1' }}&per_page={{ context.per_page }}" aria-label="Next">
        <span aria-hidden="true">下一页</span>
      </a>
    </li>
  </ul>

2.内置分页需要的引用的库

Paginator

引用导入

In [1]: from teacher.models import Student                                                                                                                                                                            

In [2]: from django.core.paginator import Paginator     

必须要在排序的基础上分页,进行实例化,前面的参数是可迭代对象,第二个参数为per_page,每页显示的数据,必须是整数

In [3]: p = Paginator(Student.objects.all().order_by('-c_time'),3) 

查看实例的成员个数

In [5]: p.count                                                                                                                                                                                                       
Out[5]: 16

In [6]: Student.objects.all().count()                                                                                                                                                                                 
Out[6]: 16

返回总页数

In [7]: p.num_pages                                                                                                                                                                                                   
Out[7]: 6

页面范围

In [8]: p.page_range                                                                                                                                                                                                  
Out[8]: range(1, 7)

通过索引的方式,基于1的数据

In [9]: page1 = p.page(1)                                                                                                                                                                                             

In [10]: page1.object_list                                                                                                                                                                                            
Out[10]: <QuerySet [<Student: 22-缇子-23>, <Student: 21-李涛-12>, <Student: 20-小泼-22>]>

查看是否有上一页,是否有下一页

In [11]: page1.has_previous()                                                                                                                                                                                         
Out[11]: False

In [12]: page1.has_next()                                                                                                                                                                                             
Out[12]: True

返回下一页的页码

In [13]: page1.next_page_number()                                                                                                                                                                                     
Out[13]: 2

下面的实例操作根据内置分页工具修改了部分代码。

2.内置分页

view.py(比较前面代码,修改如下)


from django.core.paginator import  Paginator

def students(request):....
    paginator = Paginator(sts,per_page)

    sts = paginator.get_page(page)  #当前页
    return render(request,'teacher/students.html',context=
    {
        'students':sts,
     'section':section,
     'search':search,
     'per_page':per_page,
     'page':page,
     })

customer_tags.py的修改如下:

@register.inclusion_tag('teacher/pagination.html',takes_context=True) #能够取到在views中所有的context的上下文
def pagination_html(context):
.... num
= 3 #总共显示多少个页码 page_num = context['page'] per_page = context['per_page'] # students = context['students'] #总学生数 total_num = context['students'].paginator.count #总页数 total_page = context['students'].paginator.num_pages #页码列表
....