参考博客:博客园-JsonJi,原文链接:https://www.cnblogs.com/Dominic-Ji/p/10881136.html
一、Auth模块是什么?
在开发一个网站的时候,不可避免要设计用户系统,它涉及到用户注册、登陆、注销、认证、修改密码等等功能;而此前我们学习cookie与session时纯手写登陆认证功能,显得十分笨拙。
Django深谙此道,它为我们提供了一个强大的用户认证模块:auth!在我们创建好一个Django项目后直接执行数据库迁移命令后,会自动生成很多表,其中session表已经接触过,还有一张重要的就是auth_user表,它为auth模块服务!
Django在启动之后就可以直接访问admin路由,它需要输入账号密码,而它的账号数据用的就是auth_user表,并且还必须是管理员用户才能进入。
二、Auth常用方法
此次学习我们将依赖于auth_user表完成用户认证的所有功能!
2.1、创建超级用户
super user,超级用户,即管理员的意思!在终端直接输入以下命令即可完成管理员的创建:
C:\Users\AERO\PycharmProjects\djangoProject1>python manage.py createsuperuser
Username (leave blank to use 'aero'): admin
Email address:
Password:
Password (again):
Superuser created successfully.
2.2、登陆功能
在之前手写登陆功能时,我们用POST.get获得用户输入的数据,这时候认证我们面临两个问题:
-
表数据如何获取?
-
密码如何对比?
2.2.1、用户认证
- 该方法自动去auth_user表拿数据。
- 自动给用户输入的密码加密后(sha256)再和表中密码的密文进行对比!
from django.contrib import auth # 必须先导入auth模块
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 必须同时传入账号和密码,不能分开!认证成功后该方法返回为一个用户对象,不匹配则返回None!
login_result = auth.authenticate(request, username=username, password=password)
if login_result: # 有值代表拿到对应的用户对象,即认证成功。
return HttpResponse('登陆成功')
else: # None即不匹配
return HttpResponse('哪凉快哪待去!')
return render(request, 'login.html')
2.2.2、保存用户状态
拿到用户对象后,判断当前用户是否存在,在则保存用户状态;只要执行了该方法,你就可以随时随地通过request.user获取到当前登录的用户对象;它是自动去django_session表里面查找对应的用户对象再给你封装到request_user中。
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
login_obj = auth.authenticate(request, username=username, password=password)
if login_obj:
auth.login(request, login_obj) # 类似于request.session[key] = login_obj
return HttpResponse('登陆成功')
else:
return HttpResponse('哪凉快哪待去!')
return render(request, 'login.html')
2.2.4、判断是否已登录
request.user.authenticated() # 判断当前用户是否登录,返回布尔值。
2.2.5、查询当前登录用户
request.user
2.3、注销功能
auth.logout(request),没错,就是这么一行代码!
def logout(request):
auth.logout(request) # request.session.flush
return redirect('/login/')
2.4、认证功能
在cookie与session的学习中,我们是自己手写认证装饰器,而现在?auth一条龙服务直接端上!!!
2.4.1、局部重定向
装饰器后面跟一个参数可以控制用户未登录重定向的url,登录后自动跳转至用户想要访问的url,这跟我们之前手写装饰器用的return redirect(f'/login/?next={path}')
是一样的,利用url传递参数给视图函数!
from django.contrib.auth.decorators import login_required # 要用装饰器必须先导入此模块
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
login_obj = auth.authenticate(request, username=username, password=password)
if login_obj:
auth.login(request, login_obj)
path = request.GET.get('next') # 老套路,登录成功后跳转至用户想要访问的url
if path:
return redirect(f'{path}')
else:
return redirect('/index/')
else:
return HttpResponse('哪凉快哪待去!')
return render(request, 'login.html')
@login_required(login_url='/login/') # login_url='/login/',检测到用户没有登录则跳转至此页面,可以不写然后自己手动重定向!
def index(request):
return HttpResponse('我是index页面')
2.4.2、全局重定向
全局重定向是在settings配置文件中添加如下配置:
LOGIN_URL = '/login/'
2.4.3、局部全局对比
全局配置,好处在于毋须重复写代码,缺点是跳转页面固定是一个;而局部就灵活了,可以随意定制,但是要手写参数与指定url!
LOGIN_URL = '/login/',那么局部的就可以删掉了
如果局部和全局都有,听谁的?我说是局部,哪个好?全局好处在于毋须重复写代码,只是跳转页面固定是一个;而局部就灵活了,可以随意定制
2.5、修改密码功能
request.user.set_password()方法,密码先判断两次密码是否一致,再对比旧密码是否正确,密码校验先后顺序不重要!
HTML代码
<body>
<form action="" method='post'>
{% csrf_token %}
<!--因为进入此页面代表一定登录成功。所以直接取值用户名展示出来并用disabled关闭修改,只看不能改!-->
<p>username:<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
<p>old_password:<input type="password" name="old_password"></p>
<p>new_password:<input type="password" name="new_password"></p>
<p>confirm_password:<input type="password" name="confirm_password"></p>
<p><input type="submit" value="提交"></p>
</form>
</body>
views代码
@login_required
def modify_passwd(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 not new_password == confirm_password:
return HttpResponse('两次密码输入不一致,请重新输入!')
if request.user.check_password(old_password): # 检查密码是否正确
request.user.set_password(new_password) # 将新密码保存至内存中
request.user.save() # 将内存中的密码写入数据库
return redirect('/login/')
else:
return HttpResponse('密码错误,请重新输入!')
return render(request, 'modify_passwd.html')
2.6、注册功能
注册就是获取用户输入的数据然后操作auth_user表写入数据,from django.constrib.auth.models import User
,User就是auth_user表!
我们也可以像以前操作ORM一样create数据,但是它有个极大的缺陷,密码是明文,我们绝不能用这样的方式!用auth给我们提供的两个方法!
2.6.1、创建普通用户
User.objects.create_user()方法可以创建普通用户
from django.contrib.auth.models import User # 必须先导入auth_user表
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
User.objects.create_user(username=username, password=password)
return redirect('/login/')
return render(request, 'register.html')
2.6.2、创建超级用户
User.objects.create_superuser(),使用该方法创建超级用户时邮箱必填!不推荐随意创建管理员用户!
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
User.objects.create_superuser(username=username, password=password, email='123@123.com')
return redirect('/login/')
return render(request, 'register.html')
2.7、方法总结
- 比对用户名和密码是否正确,auth.authenticate(request, username=username, password=password)
- 保存用户状态,auth.login(request, login_obj)
- 判断用户是否登录,request.user.authenticated()
- 获取当前登录用户,request.user.username
- 校验用户是否登录的装饰器,还有局部和全局的特点,login_required。
- 修改密码,check_password,set_password,sava。
- 注销,auth.logout(request)
- 注册,User.objects.create_user(),User.objects.create_superuser()
三、如何扩展auth_user表
3.1、两个思路:
3.1.1、外键
利用一对一关系建立外键字段就相当于多创建了一张表,但不推荐使用,因为麻烦还涉及联表操作效率低。
3.1.2、面向对象的继承
继承AbstractUser
models里写个类继承AbstractUser,然后在里面写要增加的字段,在第一次用数据库迁移命令时,auth_user表就不会再被创建出来了,而你写的类的创建的表会出现auth_user原本所有的字段加你后面增加的字段。
class UserInfo(AbstractUser):
phone = models.BigIntegerField()
这么做的好处在于你能够直接点击你自己的表,更加快速地完成操作及扩展,想干嘛就干嘛!
强调:必须是在继承之前没有执行过数据库迁移命令(auth_user没有被创建),如果当前库已经有auth_user了,那么就只能换一个库;继承的类里面不要有和auth_user重复的字段名。
修改配置文件
还需要在配置文件中告诉Django你要用自己的表替代auth_user,AUTH_USER_MODEL = '你的应用名.表名';如果自己写表替代了auth_user,那么auth_user模块的功能还可以照常使用,参考的表也会由原来的auth_user自动变为新表,Django牛皮!!!
AUTH_USER_MODEL = 'study1.UserInfo'
BBS用户表就是上述方式