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),
]