11.Django之Auth模块

1.Auth模块

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中的数据

2. 存放数据的表

2.1 数据库迁移
创建一个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

11.Django之Auth模块_第1张图片

2.2 创建超级用户
执行数据库迁移命令之后,设置一个超级用户。
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

3. 登入功能

3.1 路由层
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)
]
3.2 视图层
# 0. 导入Django三板斧
from django.shortcuts import render, redirect, HttpResponse


# Create your views here.
# 1. 登入功能
def login(request):
    # 1.0 返回登入页面
    return render(request, 'login.html')
3.3 前端页面
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>
3.4 业务逻辑
# 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获取当前用户登入的用户对象

image-20220322192251737

4. 主页功能

4.1 路由层
    # 2. 主页
    url(r'^home/', views.home),
4.2 视图层
# 2. 主页
def home(request):
    # 2.0 打印登入的用户名
    print(request.user)

    # 2.1 判断是否登入成功
    print(request.user.is_authenticated)

    # 2.2 返回主页信息
    return HttpResponse('主页内容...')

11.Django之Auth模块_第2张图片

输入账户密码提交数据
检验成功后跳转单home主页

11.Django之Auth模块_第3张图片

登入成功一次以后就可以直接访问 127.0.0.1:8000/home/

image-20220322192738402

删除django_session中的session数据
需要点 - 上次  在点0↑写入 再点 submit 提交

image-20220322193001283

访问 127.0.0.1:8000/home/
没有用户登入 打印 AnonymousUser 匿名有户。

image-20220322193232168

5. 登入装饰器

导入 用户登入验证装饰器
from django.contrib.auth.decorators import login_required
login_required    不加参数的话 换跳转到accounts下
5.1 装饰器不加参数
# 导入 用户登入验证装饰器
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/

11.Django之Auth模块_第4张图片

5.2 局部配置
局部配置:用户没有登入,跳到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/

11.Django之Auth模块_第5张图片

2. 输入账户密码并验证成功后,在跳转到需要访问的目录.

11.Django之Auth模块_第6张图片

5.3 全局配置
# setting.py 中  全局配置:没有登入跳转到指定的页面
LOGIN_URL = '/login/'

11.Django之Auth模块_第7张图片

# 视图层

# 不需要加参数
@login_required     
def home(request):
    ···
不测试了,结果和上面一模一样.
5.4 优先级与优势
* 局部优先于全局

全局配置: 代码简单,但是跳转的页面单页都去login。
局部配置: 代码多,不同的视图函数在用户没有登入的情况下可以跳到不同的页面。

一般情况下,先使用全局配置,在某个特定的需求下直接添加局部配置.

6. 修改密码

6.1 路由层
    # 3. 修改密码
    url(r'^set_password/', views.set_password)
6.2 视图层
# 3. 修改密码
def set_password(request):
    # 3.0 返回修改密码页面
    return render(request, 'set_password.html')
6.3 前端页面
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

11.Django之Auth模块_第8张图片

6.4 业务逻辑
# 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中的数据,跳转到登入页面中.

11.Django之Auth模块_第9张图片

7. 注销

7.1 路由层
# 注销
url(r'^logout/', views.logout),
7.2视图层
只有登入的用户才能注销
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/')

8. 注册用户

8.1 路由层
    # 5. 注册
    url(r'^register/', views.register)
8.2 视图层
# 5. 注册用户
def register(request):
    # 5.0 返回注册用户页面
    return render(request, 'register.html')
8.3 前端页面
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)]

8.4 业务逻辑
用户的数据会写进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)]

名称是唯一的,不要重复,不然会报错.

11.Django之Auth模块_第10张图片

9. 扩展auth_user表字段

9.1 一对一方式
一对一关系 绑定auth_user表 不推荐,几乎不会使用.
# models.py 模块中

class UserDetail(models.Model):
     phone = models.BigIntegerField()
     # 一对一关系 绑定user表
     user = models.OneToOneField(to='User')
9.2 继承
面向对象的继承, 需要导入 AbstractUser类
from django.contrib.auth.models import User, AbstractUser
app01 应用下的 models.py 中写一个类.
类继承 AbstractUser .
在类中写字段.
1.模型层
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)
2.主页点
如果继承了AbstractUser类
那么执行数据库迁移命令的时候 auth_user 表就不会再创建出来.
UserInfo表中会出现auth_user变中的所有的字段外加自己的而外字段
能够直接点击自己的表更加快速的完成操作及拓展

前提
1. 在继承之前没有执行过数据库迁移命令,auth_user没有被创建,如果已经被创建了就换一个库。
2. 继承的类里不要覆盖AbstractUser里面的默认字段。表里的字段不要动,值拓展额外的字段。
3. 在配置文件中添加 AUTH_USER_MODEL = 'app01.UserInfo'   
	# 应用名.表名 UserInfo 替换 auth_user
3.创建库
在Naivcat中创建一个库

11.Django之Auth模块_第11张图片

4.连接指定的数据库
# 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
5.测试
自己写的userinfo表代替了auth_user,auth的功能还能正常使用.

11.Django之Auth模块_第12张图片

修改登入功能测试.
# 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

11.Django之Auth模块_第13张图片

11.Django之Auth模块_第14张图片

你可能感兴趣的:(3.Django,django)