Auth模块

"""
其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表
    django_session
    auth_user
django在启动之后就可以直接访问admin路由,需要输入用户名和密码,数据参考的就是auth_user表,并且还必须是管理员用户才能进入

创建超级用户(管理员)
    python3 manage.py createsuperuser

依赖于auth_user表完成用户相关的所有功能
"""

新建一个项目、执行数据库迁移命令之后就可以看到auth_user表

以及表字段

命令行创建超级用户(管理员用户)

# 在pycharm中Terminal终端输入
# python3 manage.py createsuperuser

查看数据库:(密码是密文的)

创建完超级用户alias之后,就可以通过账号:alias,密码admin123登录到http://127.0.0.1:8000/admin/

依赖于auth_user表完成用户相关的所有功能

案例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登录功能
    url(r'^login/', views.login),

    # 校验用户是否登录
    url(r'^home/', views.home),
    url(r'^index/', views.index),

    # 修改密码
    url(r'^set_password/', views.set_password),

    # 注销
    url(r'^logout/', views.logout),

    # 注册功能
    url(r'^register/', views.register),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required  # 校验用户是否登陆装饰器
from django.contrib.auth.models import User   # 注册使用

# Create your views here.
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        # print(username)
        # 去用户表中校验数据
        # 1.表如何获取
        # 2.密码如何比对(因为数据库中存的是密文的)
        # 上面两个问题直接用auth模块就可以解决
        user_obj = auth.authenticate(request,username=username,password=password)
        if user_obj:
            # 获取上一次像访问的页面
            target_url = request.GET.get('next')
            if not target_url:
                target_url = "/home/"
            # 保存用户状态
            # 主要执行了auth.login()该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象
            auth.login(request, user_obj)  # 类似于request.session[key] = user_obj
            return redirect(target_url)
        """
        auth.authenticate干的事情:
        1.自动查找auth_user表
        2.自动给密码加密再匹配
        ps:该方法注意事项
        括号内必须同时传入用户名和密码
        不能只传用户名(一步就帮你筛选出用户对象)
        """
    return render(request,"login.html")

@login_required(login_url='/login/')   # 局部配置,用户没有登录,跳转到login_url后面指定的网址
def home(request):
    # print(request.user)  # 用户对象
    # 判断用户是否登录
    # print(request.user.is_authenticated())
    return HttpResponse("home")

@login_required(login_url='/login/')
def index(request):
    return HttpResponse("index")

@login_required(login_url='/login/')
def set_password(request):
    if request.method == "POST":
        old_password = request.POST.get("old_password")
        new_password = request.POST.get("new_password")
        confirm_password = request.POST.get("confirm_password")
        # 先校验两次密码是否一致
        if new_password == confirm_password:
            # 校验老密码是否正确
            is_right = request.user.check_password(old_password)   # 自动加密比对原密码
            if is_right:
                # 修改密码
                request.user.set_password(new_password)  # 仅仅是在修改对象的属性
                request.user.save()  # 这一步才是真正的操作数据库

        return redirect("/login/")
    return render(request,"set_password.html",locals())

# 注销
@login_required(login_url='/login/')
def logout(request):
    auth.logout(request)
    return redirect("/login/")    # request.session.flush()

def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 操作auth_user表写入数据
        User.objects.create_user(username=username,password=password)
        return redirect("/login/")
    return render(request,"register.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <input type="submit">
</form>
</body>
</html>

set_password.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
    <p>旧密码:<input type="text" name="old_password"></p>
    <p>新密码:<input type="text" name="new_password"></p>
    <p>确认密码:<input type="text" name="confirm_password"></p>
    <input type="submit">
</form>
</body>
</html>

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <h1>注册</h1>
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <input type="submit">
</form>
</body>
</html>

方法总结:

# 导入auth模块
from django.contrib import auth
# 1.比对用户名和密码是否正确
user_obj = auth.authenticate(request,username=username,password=password)  # 括号内必须同时传入用户名和密码,返回用户对象
print(user_obj)  # 用户对象  jason   数据不符合则返回None
print(user_obj.username)  # jason
print(user_obj.password)  # 密文

# 2.保存用户状态,auth模块帮你操作session表
auth.login(request,user_obj)  # 类似于request.session[key] = user_obj
# 主要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象

# 3.判断当前用户是否登陆,已经登录返回True,没有登录返回False
request.user.is_authenticated()   

# 4.获取当前登陆用户对象,如果没有登陆获取到的是AnonymousUser匿名用户
request.user     # alias <class 'app01.models.UserInfo'>


# 5.校验用户是否登陆装饰器
from django.contrib.auth.decorators import login_required
# 局部配置,直接加在视图函数上方,括号内login_url='/login/'是说明如果没有登录就跳转到login界面
    @login_required(login_url='/login/') 
# 全局配置
    # settings文件中添加
    LOGIN_URL = '/login/'
    # 视图函数上方
    @login_required
    def home(request):
    1.如果局部和全局都有 该听谁的?
    局部 > 全局
    2.局部和全局哪个好呢?
    全局的好处在于无需重复写代码 但是跳转的页面却很单一
    局部的好处在于不同的视图函数在用户没有登陆的情况下可以跳转到不同的页面

# 6.自动加密之后比对原密码,如果和原密码一样返回True,不一样返回False
is_right = request.user.check_password(old_password)

# 7.修改密码
request.user.set_password(new_password)  # 仅仅是在修改对象的属性
request.user.save()  # 这一步才是真正的操作数据库

# 8.注销
auth.logout(request)   # 类似于request.session.flush()

# 9.注册
# 操作auth_user表写入数据,需要导入User模块
from django.contrib.auth.models import User
# 创建普通用户,密码未加密(这个方法坚决不能用)
User.objects.create(username=username,password=password)  # 写入数据  不能用create 密码没有加密处理
# 创建普通用户,密码加密
User.objects.create_user(username=username,password=password)
# 创建超级用户,密码加密(了解):使用代码创建超级用户 邮箱是必填的 而用命令创建则可以不填
User.objects.create_superuser(username=username,email='123@qq.com',password=password)

设置 session 过期时间

# session 设置
SESSION_COOKIE_NAME = "sessionid"       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/"               # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None             # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False            # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True           # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600             # Session的cookie失效日期(2周)(数字为秒数)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False       # 是否每次请求都保存Session,默认修改之后才保存(默认)

1、在settings.py文件任意位置(推荐底部,方便查找)添加即可
2、如果设置的是默认参数,那么可以比用添加到settings.py,比如说我想设置Session的失效日期为1天,那么我只需要在settings.py文件下添加·SESSION_COOKIE_AGE = 86400即可。
3、SESSION_SAVE_EVERY_REQUEST = True和SESSION_EXPIRE_AT_BROWSER_CLOSE = True 需同时设置,否则会导致过期时间无法生效

如何扩展auth_user表

第一种方法,一对一关联表

# 伪代码
# 第一种:一对一关系  不推荐
# from django.db import models
# from django.contrib.auth.models import User

# class UserDetail(models.Model):
#     phone = models.BigIntegerField()
#     user = models.OneToOneField(to='User')

第二种方法:面向对象的继承

from django.db import models
from django.contrib.auth.models import AbstractUser   # AbstractUser扩展auth_user表使用
# Create your models here.

# 第二种:面向对象的继承,写个类继承AbstractUser
class UserInfo(AbstractUser):
    phone = models.BigIntegerField()
    """
    如果继承了AbstractUser
    那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了
    而UserInfo表中会出现auth_user所有的字段,外加自己扩展的字段
    这么做的好处在于你能够直接点击你自己的表更加快速的完成操作及扩展

    前提:
        1.在继承之前没有执行过数据库迁移命令
            auth_user没有被创建,如果当前库已经创建了那么你就重新换一个库
        2.继承的类里面不要覆盖AbstractUser里面的字段名
            表里面有的字段都不要动,只扩展额外字段即可
        3.需要在配置文件中告诉django你要用UserInfo替代auth_user(******),在settings.py中添加如下一行
            AUTH_USER_MODEL = 'app01.UserInfo'
                                '应用名.表名(就是models.py中的类名)'
    """
"""
你如果自己写表替代了auth_user那么
auth模块的功能还是照常使用,参考的表页由原来的User.变成了models.UserInfo.(就是注册功能要注意)
之前注册用户
User.objects.create_user(username=username,password=password)
现在改为
from app01 import models
models.UserInfo.objects.create_user(username=username,password=password,phone=phone)


我们bbs作业用户表就是用的上述方式
"""

扩展auth_user表 示例

示例:注意在设计表的时候,也就是auth_user表还未创建出来

  • 1、models.py创建类并继承AbstractUser,扩展字段不要与原来字段冲突
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.

# 第二种:面向对象的继承
class UserInfo(AbstractUser):
    """
    如果继承了AbstractUser
    那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了
    而UserInfo表中会出现auth_user所有的字段外加自己扩展的字段
    这么做的好处在于你能够直接点击你自己的表更加快速的完成操作及扩展

    前提:
        1.在继承之前没有执行过数据库迁移命令
            auth_user没有被创建,如果当前库已经创建了那么你就重新换一个库
        2.继承的类里面不要覆盖AbstractUser里面的字段名
            表里面有的字段都不要动,只扩展额外字段即可
        3.需要在配置文件中告诉django你要用UserInfo替代auth_user(******)
            AUTH_USER_MODEL = 'app01.UserInfo'
                                '应用名.表名'
    """
    phone = models.BigIntegerField()
    create_time = models.DateTimeField(auto_now_add=True)
  • 2、settings.py中告诉django你要用扩展表替代auth_user,在settings.py中添加如下一行
# auth表配置
AUTH_USER_MODEL = 'app01.UserInfo'
                  '应用名.表名'
  • 3、执行数据库迁移命令(注意使用MySQL要在init文件中做操作)
# python3 manage.py makemigrations
# python3 manage.py migrate

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登录功能
    url(r'^login/', views.login),

    # 校验用户是否登录
    url(r'^home/', views.home),
    url(r'^index/', views.index),

    # 修改密码
    url(r'^set_password/', views.set_password),

    # 注销
    url(r'^logout/', views.logout),

    # 注册功能
    url(r'^register/', views.register),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required  # 校验用户是否登陆装饰器
from django.contrib.auth.models import User   # 注册使用
from app01 import models

# Create your views here.
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        # print(username)
        # 去用户表中校验数据
        # 1.表如何获取
        # 2.密码如何比对(因为数据库中存的是密文的)
        # 上面两个问题直接用auth模块就可以解决
        user_obj = auth.authenticate(request,username=username,password=password)
        if user_obj:
            # 主要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象
            target_url = request.GET.get('next')
            if not target_url:
                target_url = "/home/"
            # 保存用户状态
            auth.login(request, user_obj)  # 类似于request.session[key] = user_obj
            return redirect(target_url)
        """
        auth.authenticate干的事情:
        1.自动查找auth_user表
        2.自动给密码加密再匹配
        ps:该方法注意事项
        括号内必须同时传入用户名和密码
        不能只传用户名(一步就帮你筛选出用户对象)
        """
    return render(request,"login.html")

@login_required(login_url='/login/')   # 局部配置,用户没有登录,跳转到login_url后面指定的网址
def home(request):
    # print(request.user)  # 用户对象
    # 判断用户是否登录
    # print(request.user.is_authenticated())
    return HttpResponse("home")

@login_required(login_url='/login/')
def index(request):
    return HttpResponse("index")

@login_required(login_url='/login/')
def set_password(request):
    if request.method == "POST":
        old_password = request.POST.get("old_password")
        new_password = request.POST.get("new_password")
        confirm_password = request.POST.get("confirm_password")
        # 先校验两次密码是否一致
        if new_password == confirm_password:
            # 校验老密码是否正确
            is_right = request.user.check_password(old_password)   # 自动加密比对原密码
            if is_right:
                # 修改密码
                request.user.set_password(new_password)  # 仅仅是在修改对象的属性
                request.user.save()  # 这一步才是真正的操作数据库

        return redirect("/login/")
    return render(request,"set_password.html",locals())

# 注销
@login_required(login_url='/login/')
def logout(request):
    auth.logout(request)
    return redirect("/login/")    # request.session.flush()

def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        phone = request.POST.get("phone")
        # 操作auth_user表写入数据
        models.UserInfo.objects.create_user(username=username,password=password,phone=phone)
        return redirect("/login/")
    return render(request,"register.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <input type="submit">
</form>
</body>
</html>

set_password.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
    <p>旧密码:<input type="text" name="old_password"></p>
    <p>新密码:<input type="text" name="new_password"></p>
    <p>确认密码:<input type="text" name="confirm_password"></p>
    <input type="submit">
</form>
</body>
</html>

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap3 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- font-awesome.min.css图标库4.7版本 -->
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <h1>注册</h1>
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="text" name="password"></p>
    <p>手机号:<input type="text" name="phone"></p>
    <input type="submit">
</form>
</body>
</html>
文档更新时间: 2022-03-14 17:40   作者:李延召