Django 之Auth模块
一、Auth 模块是什么
Auth 模块是Django中自带的用户认证模块。
一个网站系统需要实现用户注册、用户登录、用户认证、注销、修改密码等功能,Django中内置了强大的认证系统-auth,默认使用 auth_user 表来存储用户的数据。
同时Django有一个后台管理系统(127.0.0.1:8000/admin),使用的用户名和密码也是这张数据表中的数据。
默认后台管理的用户名和密码是没有的,需要我们创建一个出来,而且只有超级管理员才能登录这个页面,那我们现在就来创建这样一个超级用户。
二、扩展默认的 auth_user 表
在一个新的项目中,先设计项目的数据库,表关系,Django 系统内置的认证系统(auth_user表)很好用,但是表字段都是固定的几个,无法进行对它扩展。
比如,默认字段不够我们使用,我们可以对其进行拓展,存储用户手机号、时间等字段,设置表和表之间关系,怎么办?
现在就来设计扩展一下这个表,需要两步
1 配置settings
在 settings.py 配置文件中增加一句话,告诉Django 使用新定义的 UserInfo 表来做用户认证的表。
# settings.py
# 声明使用自定义表作为用户验证,声明格式为: 应用名.表名,继承使用时需要设置
AUTH_USER_MODEL = "app.UserInfo"
2 配置models
创建一个自定义类并继承AbstractUser类,然后编写 AbstractUser 类中没有的字段并且”不能冲突”。
# app/models.py
from django.db import models
# 导入AbstractBaseUser类,继承AbstractBaseUser类,基本字段
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
扩展用户信息表
继承原有的auth_user表字段
"""
nid = models.AutoField(primary_key = True)
phone = models.CharField(max_length = 11, blank = True, null = True, unique = True, verbose_name = "手机号")
avatar = models.FileField(upload_to = "avatar", default = "avatar/default.png")
create_time = models.DateField(auto_now_add = True)
blog = models.OneToOneField(to = "Blog", null = True, to_field = "bid", on_delete = models.CASCADE)
class Meta:
verbose_name_plural = "用户表"
def __str__(self):
return self.username
class Blog(models.Model):
bid = models.AutoField(primary_key = True)
site_name = models.CharField(verbose_name = "站点名称", max_length = 32)
site_title = models.CharField(verbose_name = "站点标题", max_length = 32)
site_theme = models.CharField(verbose_name = "站点样式", max_length = 255)
def __str__(self):
return self.site_name
最后,执行两条数据库迁移命令。
python manage.py makemigrations
python manage.py migrate
注意:所在的库必须是第一次执行迁移命令才可以,若是原本有残留会 引起异常。
三、创建超级用户
默认后台管理的用户名和密码是没有的,需要我们创建一个出来,而且只有超级管理员才能登录这个页面,那我们现在就来创建这样一个超级用户
python manage.py createsuperuser
四、Auth 模块常用方法
1 auth模块常用方法
from django.contrib import auth
2 authenticate()
校验用户名和密码是否正确,可以用来判断当前是否登录,也就是否有session数据。
from django.shortcuts import render, HttpResponse, redirect
from django.contrib import auth
def login(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user_obj = auth.authenticate(request, username=username, password=password)
print(user_obj)
if user_obj:
# 保存用户状态
auth.login(request, user_obj)
return HttpResponse("OK")
return render(request, "login.html")
authenticate方法如果认证成功(用户名和密码正确有效,就是去 UserInfo 表中查询一下是否存在这条记录),便会返回一个 User 对象,查询认证失败返回None。
templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>password:<input type="text" name="password"></p>
<input type="submit">
</form>
</body>
</html>
3 login(HttpRequest, user)
该函数接受一个 HttpRequest 对象,以及一个经过认证的 User 对象。
可以在验证成功后进行登录,它本质上会在后端为该用户生成相关session数据。
# 保存用户状态,相当于设置 session 值。
# 只要执行了此操作,后面的视图函数只要能够拿到request就可以通过 request.user 获取到当前的用户对象。
auth.login(request, user_obj)
4 logout(request)
该函数接受一个HttpRequest对象,无返回值。注销。
当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
def logout(request):
# 类似于request.session.flush()
auth.logout(request)
return redirect("/login/")
5 is_authenticated()
用来判断当前请求是否通过了认证。
def home(request):
print(request.user) # 用户对象 AnonymousUser匿名用户
print(request.user.is_authenticated())
if not request.user.is_authenticated():
return redirect("/home/")
return redirect("/register/")
6 login_requierd()
校验用户是否登录的装饰器。
判断当前用户是否登录那种方式很复杂,需要再每个功能函数中写上这么一段,那么auth模块也帮我们提供了一个现成的登录认证装饰器。
from django.contrib.auth.decorators import login_required
# auth 模块提供的登录装饰器提供两个配置: 局部配置和全局配置
# 局部配置
@login_required(login_url="/login/") # 用户没有登录会跳到login页面
def home(request):
# if not request.user.is_authenticated:
# return redirect("/login/")
return HttpResponse("欢迎来到home页面")
# 全局配置:
# settings.py配置文件中配置
LOGIN_URL = "/login/"
# 如果全局配置和局部配置都设置了,那么会以局部配置优先。
7 create_superuser()
auth 提供的一个创建新普通用户/超级管理员用户的方法,需要提供必要参数(username、password)等。
from app import models
# 操作auth_user表写入数据
def register(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
# 写入数据不能用create密码没有加密处理
# models.UserInfo.objects.create(username=username, password=password)
# 创建普通用户
# models.UserInfo.objects.create_user(username=username, password=password)
# 创建超级用户(了解):使用代码创建超级用户 邮箱是必填的 而用命令创建则可以不填
models.UserInfo.objects.create_superuser(username=username, password=password, email="iyuyi.xyz@gmail.com")
return render(request, "register.html")