auth 用户认证模块 本质是设置session
django执行ORM数据库迁移会在数据库中自动生成一个用户认证的表: auth_user,
auth_user 存放用户的账户信息(用户名, 加密密码, 邮箱...)
0. 导入auth模块
from django.contrib import auth
1. auth.authenticate(request=None, **credentials): 检验账户密码
user_obj = auth.authenticate(request, username=username, password=password)
注意事项,括号内必须同时传入用户和密码。
自动查找auth_user表,给密码加密再检验,该方法有一个返回值 为真 值为用户对象, 否则返回None
2. auth.login(request, user, backend=None)
保存用户登入状态,将用户信息写入session中
3. request.user
去django_session表里面查询对应的用户对象,封装给request.user.
返回获取登入用户的名称.
没有用户登入 打印 AnonymousUser 匿名有户
4. request.user.is_authenticated()
判断用户是否登入。 CallableBool(True) / CallableBool(False)
5. auth.logout(request) 清除数据 只有登入的用户才能注销
类似 request.session.flush 清除 session中的数据
创建一个django项目
执行数据库迁移命令会自动生成几张表, auth_user在其中
django在启动之后就可以访问admin路由,需要输入用户名和密码,数据参考的就是auth_user表,
并且还需要管理员用户才能进去。
PS F:\synchro\Project\django10> python manage.py makemigrations
No changes detected
PS F:\synchro\Project\django10> python manage.py migrate
Operations to perform:
....OK
执行数据库迁移命令之后,设置一个超级用户。
I:\备份\test\django10>python manage.py createsuperuser
Username (leave blank to use '13600'): kid
Email address: 13600@qq.com
Password:kid123456
Password (again):kid123456
密码不显示的···不要设置纯数字
密码加密 sha256
from django.conf.urls import url
from django.contrib import admin
# 0. 导入视图层
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 1. 登入功能
url(r'^login/', views.login)
]
# 0. 导入Django三板斧
from django.shortcuts import render, redirect, HttpResponse
# Create your views here.
# 1. 登入功能
def login(request):
# 1.0 返回登入页面
return render(request, 'login.html')
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登入功能title>
head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>名称: <input type="text" name="username">p>
<p>密码: <input type="password" name="password">p>
<input type="submit"><span style="color:red">{{ error_msg.msg }}span>
form>
body>
html>
# 0. 导入Django三板斧
from django.shortcuts import render, redirect, HttpResponse
# Create your views here.
# 1. 登入功能
def login(request):
# 1.1 判断提交方式
if request.method == 'POST':
# 1.2 POST用户数据
post_obj = request.POST
username = post_obj.get('username')
password = post_obj.get('password')
# 1.3 使用 auth模块 账户密码校验
from django.contrib import auth
user_obj = auth.authenticate(request, username=username, password=password)
# 1.4 判断对比结果
if user_obj:
# 1.5 查看数据对象的信息
print(user_obj.username)
print(user_obj.password)
# 1.6 保存用户的登入状态 === request.session[key] = user_obj
auth.login(request, user_obj)
# 1.7 返回登入后的页面
return redirect('/home/')
else:
error_msg = {'msg': '账户或密码不对!'}
return render(request, 'login.html', locals())
# 1.0 返回登入页面
return render(request, 'login.html')
auth.login(request, user_obj) === request.session[key] = user_obj
校验数据成功之后将数据写入session中.
只要执行了该方法就可以在任何有request的地方通过request.user获取当前用户登入的用户对象
# 2. 主页
url(r'^home/', views.home),
# 2. 主页
def home(request):
# 2.0 打印登入的用户名
print(request.user)
# 2.1 判断是否登入成功
print(request.user.is_authenticated)
# 2.2 返回主页信息
return HttpResponse('主页内容...')
输入账户密码提交数据
检验成功后跳转单home主页
登入成功一次以后就可以直接访问 127.0.0.1:8000/home/
删除django_session中的session数据
需要点 - 上次 在点0↑写入 再点 submit 提交
访问 127.0.0.1:8000/home/
没有用户登入 打印 AnonymousUser 匿名有户。
导入 用户登入验证装饰器
from django.contrib.auth.decorators import login_required
login_required 不加参数的话 换跳转到accounts下
# 导入 用户登入验证装饰器
from django.contrib.auth.decorators import login_required
# 登入装饰器
@login_required
# 2. 主页
def home(request):
# 2.0 打印登入的用户名
print(request.user)
# 2.1 判断是否登入成功
print(request.user.is_authenticated)
# 2.2 返回主页信息
return HttpResponse('主页内容...')
在浏览器中直接输入 127.0.0.1:8000/home/
直接跳转到 http://127.0.0.1:8000/accounts/login/?next=/home/
局部配置:用户没有登入,跳到login_url后面的地址
@login_required(login_url='/xxxx/')
def home(request):
...
# 导入 用户登入验证装饰器
from django.contrib.auth.decorators import login_required
# 登入装饰器局部配置
@login_required(login_url='/login/')
# 2. 主页
def home(request):
# 2.0 打印登入的用户名
print(request.user)
# 2.1 判断是否登入成功
print(request.user.is_authenticated)
# 2.2 返回主页信息
return HttpResponse('主页内容...')
0. 在浏览器中输入 127.0.0.1:8000/home/
1. 跳转到指定的页面中, 并携带需要登入的目录,
http://127.0.0.1:8000/login/?next=/home/
2. 输入账户密码并验证成功后,在跳转到需要访问的目录.
# setting.py 中 全局配置:没有登入跳转到指定的页面
LOGIN_URL = '/login/'
# 视图层
# 不需要加参数
@login_required
def home(request):
···
不测试了,结果和上面一模一样.
* 局部优先于全局
全局配置: 代码简单,但是跳转的页面单页都去login。
局部配置: 代码多,不同的视图函数在用户没有登入的情况下可以跳到不同的页面。
一般情况下,先使用全局配置,在某个特定的需求下直接添加局部配置.
# 3. 修改密码
url(r'^set_password/', views.set_password)
# 3. 修改密码
def set_password(request):
# 3.0 返回修改密码页面
return render(request, 'set_password.html')
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改密码title>
<style>
span {
color: red;
}
style>
head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>旧密码: <input type="password" name="old_password"><span>{{ error_msg.old_password }}span>p>
<p>新密码: <input type="password" name="new_password">p>
<p>确认密码: <input type="password" name="confirm_password"><span>{{ error_msg.confirm_password }}span>p>
<input type="submit">
form>
body>
html>
在流浪器中 输入 127.0.0.1:8000/set_password
# 3. 修改密码
def set_password(request):
# 3.1 判断数据提交方式
if request.method == 'POST':
# 3.2 获取用户数据
post_obj = request.POST
old_password = post_obj.get('old_password')
new_password = post_obj.get('new_password')
confirm_password = post_obj.get('confirm_password')
# 3.3 判断用户输入的两次密码是否一致
if new_password == confirm_password:
# 3.4 校验用户输入的密码是否正确 --> 返回布尔值
is_right = request.user.check_password(old_password)
# 3.5 密码正确修改密码
if is_right:
# 3.6 将数据写到user对象中属性的值
request.user.set_password(new_password)
# 3.7 将数据保存
request.user.save()
print('修改成功')
# 3.8 清除session数据 重新登入的页面
from django.contrib import auth
auth.logout(request) # 类似 request.session.flush
return redirect('/login/')
# 3.9 密码不正则
else:
error_msg = {'old_password': '密码错误!'}
# 3.10 两次密码不一致
else:
error_msg = {'confirm_password': '两次密码不一致!'}
# 3.11 返回错误的信息
return render(request, 'set_password.html', locals())
# 3.0 返回修改密码页面
return render(request, 'set_password.html')
在浏览器中输入 127.0.0.1:8000/set_password
输入正确的密码...
修改成功后,清除session中的数据,跳转到登入页面中.
# 注销
url(r'^logout/', views.logout),
只有登入的用户才能注销
auth.logout(request) # 类似 request.session.flush 清除 session中的数据
# 4. 注销登入 (只有登入的用户才能注销)
@login_required(login_url='/login/')
def logout(request):
# 4.0 清除 session中的数据
from django.contrib import auth
auth.logout(request)
# 4.1 跳转到登入页面
return redirect('/login/')
# 5. 注册
url(r'^register/', views.register)
# 5. 注册用户
def register(request):
# 5.0 返回注册用户页面
return render(request, 'register.html')
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面title>
head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>名称: <input type="text" name="username">p>
<p>密码: <input type="password" name="password">p>
<p>邮箱: <input type="email" name="email">p>
<input type="submit">
form>
body>
html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JXoj7u0s-1647966326626)(https://s2.loli.net/2022/03/22/vb5yGFgEoOWYezM.png)]
用户的数据会写进auth_user 表中
导入这张表的OMR模型
from django.contrib.auth.models import User
create 写入明文的数据
create_user 写入密文的数据
create_superuser 创建超级用户, 超级用户邮箱是必须填的, 密文的数据
User.objects.create_superuser(username=username,email='13600@qq', password=password)
# 5. 注册用户
def register(request):
# 5.1 判断数据提交方式
if request.method == 'POST':
# 5.2 获取用户数据
post_obj = request.POST
username = post_obj.get('username')
password = post_obj.get('password')
email = post_obj.get('email')
# 5.3 操作User表
from django.contrib.auth.models import User
"""
操作auth_user表
注册普通用户
create 写入明文的数据
create_user 写入密文的数据
User.objects.create(username=username, password=password, email=email)
"""
User.objects.create_user(username=username, password=password, email=email)
# 5.5 返回到登入功能去检测
return redirect('/login/')
# 5.0 返回注册用户页面
return render(request, 'register.html')
在浏览器中输入 127.0.0.1:8000/register
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vTc7mgP8-1647966326626)(https://s2.loli.net/2022/03/22/lO4hsQbASm6Mkez.png)]
名称是唯一的,不要重复,不然会报错.
一对一关系 绑定auth_user表 不推荐,几乎不会使用.
# models.py 模块中
class UserDetail(models.Model):
phone = models.BigIntegerField()
# 一对一关系 绑定user表
user = models.OneToOneField(to='User')
面向对象的继承, 需要导入 AbstractUser类
from django.contrib.auth.models import User, AbstractUser
app01 应用下的 models.py 中写一个类.
类继承 AbstractUser 类.
在类中写字段.
from django.db import models
# Create your models here.
# 0. 导入 AbstractUser 类
from django.contrib.auth.models import AbstractUser
# 1. 创建映射表的类 继承 AbstractUser 类
class UserInfo(AbstractUser):
# 1.1 创建额外的字段
create_time = models.DateTimeField(auto_now_add=True)
如果继承了AbstractUser类
那么执行数据库迁移命令的时候 auth_user 表就不会再创建出来.
UserInfo表中会出现auth_user变中的所有的字段外加自己的而外字段
能够直接点击自己的表更加快速的完成操作及拓展
前提
1. 在继承之前没有执行过数据库迁移命令,auth_user没有被创建,如果已经被创建了就换一个库。
2. 继承的类里不要覆盖AbstractUser里面的默认字段。表里的字段不要动,值拓展额外的字段。
3. 在配置文件中添加 AUTH_USER_MODEL = 'app01.UserInfo'
# 应用名.表名 UserInfo 替换 auth_user
在Naivcat中创建一个库
# settings.py
DATABASES = {
'default': {
# 使用的引擎
'ENGINE': 'django.db.backends.mysql',
# IP
'HOST': '127.0.0.1',
# 端口
'PORT': 3306,
# 库的名称
'NAME': 'day10',
# 登入的用户
'USER': 'root',
# 登入的密码
'PASSWORD': 123,
# 使用的编码
'CHARSET': 'utf8'
}
}
# auth 表配置
AUTH_USER_MODEL = 'app01.UserInfo'
# app01 应用下 __init__.py
import pymysql
pymysql.install_as_MySQLdb()
执行数据迁移命令。
python manage.py makemigrations
python manage.py migrate
自己写的userinfo表代替了auth_user,auth的功能还能正常使用.
修改登入功能测试.
# 5. 注册用户
def register(request):
# 5.1 判断数据提交方式
if request.method == 'POST':
# 5.2 获取用户数据
post_obj = request.POST
username = post_obj.get('username')
password = post_obj.get('password')
email = post_obj.get('email')
# 5.3 操作User表
from app01 import models
models.UserInfo.objects.create_user(username=username, password=password, email=email)
# 5.5 返回到登入功能去检测
return redirect('/login/')
# 5.0 返回注册用户页面
return render(request, 'register.html')
在浏览器中输入 127.0.0.1:8000/register