Django视图 (CBV | 自定义分页)

Django视图

Django视图之CBV

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('login.html$', views.Login.as_view()),
]

views.py

from django.views import View

# 对于来自get和post请求做出的响应做区分
class Login(View):
    def get(self, request):
        # return HttpResponse('Login.get')
        return render(request, 'login.html')

    def post(self, request):
        print(request.POST.get('user'))
        return HttpResponse('Login.post')

Django视图之内置分页

# 分批获取数据
models.UserInfo.objects.all()[0:10]
models.UserInfo.objects.all()[10:20]

views.py

from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage


def index(request):
    """
    分页
    :param request:
    :return:
    """

    # for i in range(300):
    #     name = 'root' + str(i)
    #     models.UserInfo.objects.create(name=name, age=18, ut_id=1)

    
    current_page = request.GET.get('page')  # 获取当前页的值

    user_list = models.UserInfo.objects.all()
    paginator = Paginator(user_list, 10)
    # per_page: 每页显示条目数量
    # count: 数据总个数
    # num_pages: 总页数
    # page_range: 总页数的索引范围,如:(1,10),(1,200)
    # page: page对象

    try:
        posts = paginator.page(current_page)
        # has_next: 是否有下一页
        # next_page_number: 下一页页码
        # has_previous: 是否有上一页
        # previous_page_number: 上一页页码
        # object_list: 分页之后的数据列表
        # number: 当前页
        # paginator: paginator对象
    except PageNotAnInteger as e:
        # 捕获异常,如果页码不是整数,就返回第一页
        posts = paginator.page(1)
    except EmptyPage as e:
        # 捕获异常,如果页码为空,就返回第一页
        posts = paginator.page(1)

    return render(request, 'index.html', {'posts': posts})

index.html

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

<h1>用户列表</h1>
<ul>
    {% for row in posts.object_list %}
        <li>{{ row.name }}</li>
    {% endfor %}
</ul>
<div>

    {% if posts.has_previous %}
        <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
    {% endif %}

    {% for num in posts.paginator.page_range %}
        <a href="/index.html?page={{ num }}">{{ num }}</a>
    {% endfor %}


    {% if posts.has_next %}
        <a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
    {% endif %}
</div>
</body>
</html>

urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('index.html$', views.index),
]

Django内置的分页缺点:

​ 只是适应于上一页和下一页。

​ 比如:若是有一万页,那么下面将会把一万页的页码都显示出来,明显不合理。

自定义分页

views.py

def custom(request):
    # 表示用户当前想要访问的页码
    current_page = request.GET.get('page')
    current_page = int(current_page)

    # 每页显示数据个数
    per_page = 10
    start = (current_page - 1) * per_page
    end = current_page * per_page

    user_list = models.UserInfo.objects.all()[start:end]

    return render(request, 'custom.html', {'user_list': user_list})
  

urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('custom.html$', views.custom),
]

custom.html

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

<h1>用户列表</h1>
<ul>
    {% for row in posts.object_list %}
        <li>{{ row.name }}</li>
    {% endfor %}
</ul>
</body>
</html>

改善后的自定义分页

views.py

from django.shortcuts import render, HttpResponse
from utils.pager import PageInfo
from app01 import models


def custom(request):
    # 计算数据条目的总个数
    all_count = models.UserInfo.objects.all().count()

    page_info = PageInfo(request.GET.get('page'), all_count, 10, '/custom.html')
    user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]

    return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})


pager.py (类)

from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage


class PageInfo():
    def __init__(self, current_page, all_count, per_page, base_url, show_page=11):

        """

        :param current_page: 当前页码
        :param all_count: 数据库条目总个数
        :param per_page: 每页显示的个数
        :param base_url: 要填转到额路径
        :param show_page: 一次显示的页数
        """

        try:
            self.current_page = int(current_page)
        except PageNotAnInteger as e:
            self.current_page = 1
        except EmptyPage as e:
            self.current_page = 1
        self.per_page = per_page

        a, b = divmod(all_count, per_page)  # a为商,b为余数
        if b:  # 如果有余数,则再多一行
            a = a + 1

        self.all_page = a  # 总页码
        self.show_page = show_page
        self.base_url = base_url

    def start(self):
        return (self.current_page - 1) * self.per_page

    def end(self):
        return self.current_page * self.per_page

    def page(self):
        # v = "<a href='/custom.html?page=1'>1</a>"
        # return v

        page_list = []
        half = int((self.show_page - 1) / 2)

        # 如果数据总页数小于11
        if self.all_page < self.show_page:
            begin = 1
            stop = self.all_page + 1
        # 如果总页数大于11
        else:
            # 如果当前页小于等于5,永远显示1-11
            if self.current_page <= half:
                begin = 1
                stop = self.show_page + 1
            else:
                # 如果
                if self.current_page + half > self.all_page:
                    begin = self.all_page - self.show_page + 1
                    stop = self.all_page + 1
                else:
                    begin = self.current_page - half
                    stop = self.current_page + half + 1

        if self.current_page <= 1:
            prev = "<li><a href='#'>上一页</a></li>"
        else:
            prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page - 1)
        page_list.append(prev)

        for i in range(begin, stop):
            # 后台直接向前台传html代码
            if i == self.current_page:
                temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
            else:
                temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
            page_list.append(temp)

        if self.current_page >= self.all_page:
            nex = "<li><a href='#'>下一页</a></li>"
        else:
            nex = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1)
        page_list.append(nex)

        return ' '.join(page_list)

custom.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户列表</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1-dist/css/bootstrap.css">
</head>
<body>
<h1>用户列表</h1>
<ul>
    {% for row in user_list %}
        <li>{{ row.name }}</li>
    {% endfor %}
</ul>


<nav aria-label="Page navigation">
    <ul class="pagination">
        {{ page_info.page | safe }}


    </ul>
</nav>
</body>
</html>

urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('custom.html$', views.custom),
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值