1.auth模块
auth模块是Django提供的标准权限管理系统,可以提供用户身份认证,和权限管理
auth可以和admin模块配合使用, 快速建立网站的管理系统
在INSTALLED_APPS中添加'django.contrib.auth'使用该APP, auth模块默认启用
导入auth模块
from django.contrib import auth
1.1 authenticate() :验证用户输入的用户名和密码是否相同
提供用户认证,即验证用户名以及密码是否正确,一般需要username password(django的auth_user自带数据库就有的名字)两个关键字参数
user = authenticate(username='someone',password='somepassword')
1.2 auth.login(request,user) :此函数使用django的session框架给某个已认证的用户附加上session id等信息
设置完成后request.user就是全局的变量了,直接可以随意随时随地的使用request.user进行取值
auth.login(request,user) # 直接使用
1.3 logout(request): 注销用户,无返回值,当前请求的session信息会在数据路中全部清除
auth.logout(request)
1.4 user对象的is_authenticated() 登录验证,用户登录后才能访问页面,没有登录则跳转到登录页
if not request.user.is_authenticated:
return redirect("/login/")
对于此,我们也可以使用django提供的组件装饰器:login_required()
from django.contrib.auth.decorators import login_required @login_required
def my_view(request):
...
1.5 创建用户
在django自带的auth_user中创建用户,注意导入方式
from django.contrib.auth.models import User
def register(request):
User.objects.create(username="luffy",password=123)
return redirect("/login/")
1.6 修改密码 set_password()
user = User.objects.get(username='')
user.set_password(password='')
user.save
2.演示代码
url.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path("login/",views.login),
path("index/",views.index),
path("logout/",views.logout),
]
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<form action="" method="post">
{% csrf_token %}
用户名:<input type="text" name="user">
密码:<input type="password" name="pwd">
<input type="submit">
</form>
<body> </body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>Hi, {{ request.user.username }} <a href="/logout/">注销</a></h3>
</body>
</html>
views.py
登录
rom django.shortcuts import render,redirect # 导入用户认证组件,auth模块
from django.contrib import auth def login(request):
if request.method=="POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
# 用户验证,一致则返回user对象,否则返回none
user = auth.authenticate(username=user,password=pwd)
print(user)
if user:
# 登录成功,则注册session组件,在session中存储信息
auth.login(request,user)
return redirect("/index/")
return render(request,"login.html")
登录验证
def index(request):
# 打印存储在auth_user中的用户id,及姓名
print(request.user.id,request.user.username)
# 登录验证,用户登录后才能访问某些页面,没有登录就访问该页面则跳转登录页面
if not request.user.is_authenticated:
return redirect("/login/")
return render(request, "index.html")
注销
def logout(request):
# 注销用户,之前请求的session信息会全部清除
auth.logout(request)
return redirect("/login/")
3. 分页器(paginator)
3.1 实现方式一( 利用了django自带的paginator分页组件)
代码:
models.py
from django.db import models
class Book(models.Model):
title=models.CharField(max_length=32)
price=models.DecimalField(max_digits=8,decimal_places=2)
index.html
这里导入了bootstrap的样式,里面还有其他分页器的样式,自己可以在官网查找
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.1.0/css/bootstrap.css">
</head> <body>
<h3>INDEX</h3>
<ul>
{% for book in book_list %}
<li>{{ book.title }}>>>>{{ book.price }}</li>
{% endfor %}
</ul>
<nav aria-label="Page navigation">
<ul class="pagination">
{% for i in pageRange %}
{% if current_num == i %}
<li class="active"><a href="?page={{ i }}">{{ i }}</a></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
</ul>
</nav>
</body>
</html>
views.py
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from app01.models import Book def index(request):
# 批量导入
book_list = []
for i in range(1,101):
book = Book(title="book_%s" % i,price=i**2)
book_list.append(book)
# 批量创建列表中的对象,这样效率比硬编码创建要高得多
Book.objects.bulk_create(book_list) # 分页器
paginator = Paginator(book_list,10) # 必须的先实例化
print(paginator.count) # 总数据量
print(paginator.num_pages) # 分页数
print(paginator.page_range) #页码范围,range(1, 11) page1 = paginator.page(1) # 第一页的page对象
print(page1.start_index()) # 起始页码,1
print(page1.end_index()) # 最的页码数,10
print(page1.has_next()) # True
print(page1.has_other_pages()) # True
print(page1.has_previous()) # False
print(page1.next_page_number()) # 2
# print(page1.previous_page_number()) # 报错,没有前一页
print(page1.object_list) # 第一页的所有数据,不过得到的是对象 # 报错
# page = paginator.page(12) # error:EmptyPage
# page = paginator.page("z") # error:PageNotAnInteger
return render(request, "index.html", locals())
基于以上案例对分页器样式的设计
book_list = Book.objects.all()
paginator = Paginator(book_list, 2)
try:
current_num = int(request.GET.get("page", 1))
book_list = paginator.page(current_num)
except EmptyPage:
book_list = paginator.page(1) # 如果页数特别多时,换另外一种显示方式
if paginator.num_pages > 11: if current_num - 5 < 1:
pageRange = range(1, 11)
elif current_num + 5 > paginator.num_pages:
pageRange = range(current_num - 5, paginator.num_pages + 1) else:
pageRange = range(current_num - 5, current_num + 6) else:
pageRange = paginator.page_range return render(request, "index.html", locals())
最终效果:
3.2分页器实现方式二(自己编写分页组件)
这里的效果比上一种更加美观一些,实现原理核心部分封装成了一个类方法,直接放在我们的应用下,在视图中导入即可
pagination.py
class Pagination:
def __init__(self, page_num, total_num, per_page_num=10, max_show=11):
self.page_num = page_num # 当前页面数
self.total_num = total_num # 总数据量
self.per_page_num = per_page_num # 每页显示数据条数
self.max_show = max_show # 最多显示页码数
self.half_show = self.max_show // 2
self.total_page, more = divmod(total_num, per_page_num)
if more:
self.total_page += 1
if self.page_num > self.total_page:
self.page_num = self.total_page
elif self.page_num < 1:
self.page_num = 1 @property
def start(self):
return (self.page_num - 1) * self.per_page_num @property
def end(self):
return self.page_num * self.per_page_num @property
def page_html(self):
page_start = self.page_num - self.half_show
page_end = self.page_num + self.half_show + 1
if self.page_num + self.half_show >= self.total_page:
page_end = self.total_page + 1
page_start = self.total_page - self.max_show + 1
if self.page_num <= self.half_show:
page_start = 1
page_end = self.max_show + 1
page_num_list = [] # 添加首页
page_num_list.append('<li><a href="/user_list/?page={0}">首页</a></li>'.format(1))
# 添加上一页
pre_page_num = self.page_num - 1
if pre_page_num < 1:
page_num_list.append(
'<li class="disabled"><a href="/user_list/?page={0}">上一页</a></li>'.format(pre_page_num))
else:
page_num_list.append('<li><a href="/user_list/?page={0}">上一页</a></li>'.format(pre_page_num)) for i in range(page_start, page_end):
if i == self.page_num:
page_num_list.append('<li class="active"><a href="/user_list/?page={0}">{0}</a></li>'.format(i))
else:
page_num_list.append('<li><a href="/user_list/?page={0}">{0}</a></li>'.format(i))
# 添加下一页
next_page_num = self.page_num + 1
if next_page_num > self.total_page:
page_num_list.append(
'<li class="disabled"><a href="/user_list/?page={0}">下一页</a></li>'.format(next_page_num))
else:
page_num_list.append('<li><a href="/user_list/?page={0}">下一页</a></li>'.format(next_page_num)) # 添加尾页
page_num_list.append('<li><a href="/user_list/?page={0}">尾页</a></li>'.format(self.total_page)) page_html = ''.join(page_num_list) return page_html
url.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('user_list/',views.user_list)
]
views.py
from django.shortcuts import render data = []
for i in range(1, 302):
data.append({'name': '%s只羊' % i, 'age': '%s只' % i}) def user_list(request):
from . import pagination # 从应用中导入我们创建的分页文件
try:
page_num = int(request.GET.get('page', 1)) # 这里的get请求是在url上
except Exception:
page_num = 1
# 实例化对象
page_obj =pagination.Pagination(page_num,len(data)) data1 = data[page_obj.start:page_obj.end]
return render(request, 'user_list.html', {'user_list': data1, 'page_html': page_obj.page_html})
user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
<div class="container">
<table class="table table-bordered">
<thead>
<tr>
<th>姓名</th>
<th>只数</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
</tr>
{% endfor %} </tbody>
</table>
</div> <div class="text-center">
<nav aria-label="Page navigation">
<ul class="pagination">
{# 加入safe,保证能够从后端将数据传到前端 #}
{{ page_html|safe }}
</ul>
</nav> </div>
</body>
</html>
最终效果:
3.3分页器实现方式三(通用类型) --->出自wusir
class Pagination(object):
def __init__(self, current_page, all_count, base_url,query_params, per_page=10, pager_page_count=11):
"""
分页初始化
:param current_page: 当前页码
:param per_page: 每页显示数据条数
:param all_count: 数据库中总条数
:param base_url: 基础URL
:param query_params: QueryDict对象,内部含所有当前URL的原条件
:param pager_page_count: 页面上最多显示的页码数量
"""
self.base_url = base_url
try:
self.current_page = int(current_page)
if self.current_page <= 0:
raise Exception()
except Exception as e:
self.current_page = 1
self.query_params = query_params
self.per_page = per_page
self.all_count = all_count
self.pager_page_count = pager_page_count
pager_count, b = divmod(all_count, per_page)
if b != 0:
pager_count += 1
self.pager_count = pager_count half_pager_page_count = int(pager_page_count / 2)
self.half_pager_page_count = half_pager_page_count @property
def start(self):
"""
数据获取值起始索引
:return:
"""
return (self.current_page - 1) * self.per_page @property
def end(self):
"""
数据获取值结束索引
:return:
"""
return self.current_page * self.per_page def page_html(self):
"""
生成HTML页码
:return:
"""
# 如果数据总页码pager_count<11 pager_page_count
if self.pager_count < self.pager_page_count:
pager_start = 1
pager_end = self.pager_count
else:
# 数据页码已经超过11
# 判断: 如果当前页 <= 5 half_pager_page_count
if self.current_page <= self.half_pager_page_count:
pager_start = 1
pager_end = self.pager_page_count
else:
# 如果: 当前页+5 > 总页码
if (self.current_page + self.half_pager_page_count) > self.pager_count:
pager_end = self.pager_count
pager_start = self.pager_count - self.pager_page_count + 1
else:
pager_start = self.current_page - self.half_pager_page_count
pager_end = self.current_page + self.half_pager_page_count page_list = [] if self.current_page <= 1:
prev = '<li><a href="#">上一页</a></li>'
else:
self.query_params['page'] = self.current_page - 1
prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url,self.query_params.urlencode())
page_list.append(prev)
for i in range(pager_start, pager_end + 1):
self.query_params['page'] = i
if self.current_page == i:
tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
self.base_url, self.query_params.urlencode(), i,)
else:
tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
page_list.append(tpl) if self.current_page >= self.pager_count:
nex = '<li><a href="#">下一页</a></li>'
else:
self.query_params['page'] = self.current_page + 1
nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
page_list.append(nex)
page_str = "".join(page_list)
return page_str