Auth模块
- 什么是auth模块?
- Auth模块是Django自带的用户认证模块:
- 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这些功能几乎是所有软件都需要开发的功能,那么我们之前在写这些功能的时候也是需要花费一些时间书写代码逻辑的,那么Django自带的auth模块就会很轻松的帮助我们完成这些功能,它默认使用 auth_user 表来存储用户数据。
- auth_user表
- # 其实我们很早就应该见过这张表只是把它忽略了。
- - 其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表,那么其中一张表就是auth_user表
-
- # 基本用处:
- - django在启动之后就可以直接访问admin路由,需要输入用户名和密码,数据参考的就是auth_user表,并且还必须是管理员用户才能进入
-
- # 怎么创建超级用户(管理员)
- - 首先要数据库迁移
- makemigrations
- migrate
- - 创建超级用户命令:
- python3 manage.py createsuperuser
接下来就使用auth_user表来实现用户的登录,注册,注销...功能:
登录功能:
- # 校验用户民或密码是否一致
- # 关键字:auth.authenticate(username=用户输入的用户名,password=用户输入的密码)
- # 需导入模块:
- from django.contrib import auth
-
-
- def login(request):
- if request.method == 'POST':
- username = request.POST.get('username')
- password = request.POST.get('password')
- # 那么现在如何校验数据呢?
- # 获取表的数据 但是密码是密文的怎么比对呢
- # 这时就要用到auth模块
- res = auth.authenticate(request,username=username,password=password)
- '''
- 他都干了那些事:
- 自动查找auth_user表
- 自动给密码加密后再进行比对
- 注意事项:
- 括号内必须同时传入用户名和密码
- 不能只传用户名
- '''
- print(res,type(res))
- print(res.username)
- print(res.password)
- return render(request,'login.html')
保存用户登陆状态
# 关键字:auth_login(request,用户对象)
- # 方法优点:只要执行了auth.login方法,就可以在任何地方通过request.user获取到当前登录的用户对象
-
-
-
- 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)
- if user_obj:
- # 之前我们保存用户登录状态是不是要通过session来保存。现在可通过auth来直接帮助我们操作session表
- # 保存用户登录状态:
- auth.login(request,user_obj) # 类似于request_session[key] = user_obj
- return redirect('/home/') # 跳转到home页面
-
-
- return render(request,'login.html')
-
- def home(request):
- print(request.user) # 可以拿到当前登录的用户对象
- return HttpResponse('home')
判断用户是否登录
# 如上:那么如果没有登录,直接访问home页面,requeest.user返回的是什么呢?
- # 结果:如果没有登录则返回的是AnonymousUser匿名用户
-
- # 那么如果判断用户是否登录了呢?
- # 关键字:request.user.is_authenticated
- # 返回结果:布尔类型:
- - 未登录(匿名用户) :返回False
- - 已登录 :返回True
校验是否登录装饰器
- # 上述看到我们匿名用户也可以登录到home页面,这样是不合理的,需要登陆后才能访问其他页面才合理。那么就需要校验用户是否登录
-
- # 需导入模块:
- - from django.contrib.auth.decorators import login_required
- # 关键字:添加装饰器
- - 局部配置:@login_required(login_url='/指定未登录跳转页面/')
- - 全局配置:@login_required # 无需指定跳转路径
- # 需要在settings.py配置文件中配置:LOGIN_URL = '/指定未登录跳转页面/'
- 局部和全局哪个好呢?
- 全局的好处在于无需重复写代码 但是跳转的页面却很单一
- 局部的好处在于不同的视图函数在用户没有登陆的情况下可以跳转到不同的页面
修改密码
- # 修改密码:
- - 需要校验旧密码是否正确
- - 需要将新密码从auth_user表中修改并保存
- <form action="" method="post">
- {% csrf_token %}
- <p>username<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
- <p>old_password:<input type="text" name="old_password"></p>
- <p>new_password:<input type="text" name="new_password"></p>
- <p>confirm_password:<input type="text" name="confirm_password"></p>
- <input type="submit">
-
- </form>
- # 校验旧密码:
- # 关键字:request.user.check_password('需要校验的数据(旧密码)')
- - 相当于:将当前表的password字段和用户输入的旧密码进行比对
-
- # 修改密码并同步到数据库:
- # 关键字:request.user.set_password(此处放新密码)
- @login_required
- 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,'setpassword.html',locals())
注销功能
- # 注销则是将session表中的用户数据删除即可。
- # 关键字:auth.logout(request)
-
-
- @login_required # 登录才能注销所以也需要验证是否登录。
- def logout(request):
- auth.logout(request)
- return redirect('/login/')
注册功能
- # 原理:操作auth_user表写入数据:
- # 关键字:User.objects.create(username=username,password=password)
-
- # 需导入模块:
- from django.contrib.auth.models import User
-
- def register(request):
- if request.method == 'POST':
- username = request.POST.get('username')
- password = request.POST.get('password')
- # 操作auth_user表写入数据
- User.objects.create(username=username,password=password)
-
- return render(request,'register.html')
- # 综上:写入数据 不能用create 密码没有加密 处理
-
- # 创建普通用户
- User.objects.create_user(username=username,password=password)
- # 创建超级用户(了解):使用代码创建超级用户 邮箱是必填的 而用命令创建则可以不填
- User.objects.create_superuser(username=username,email='123@qq.com',password=password)
总结:
- # 1.比对用户名和密码是否正确
- user_obj = auth.authenticate(request,username=username,password=password)
- # 括号内必须同时传入用户名和密码
- print(user_obj) # 返回用户对象 数据不符合则返回None
- print(user_obj.username) # 用户名
- print(user_obj.password) # 密文
-
- # 2.保存用户状态
- auth.login(request,user_obj) # 类似于request.session[key] = user_obj
- # 只要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象
-
- # 3.判断当前用户是否登陆
- request.user.is_authenticated()
-
- # 4.获取当前登陆用户对象
- request.user
-
- # 5.校验用户是否登陆装饰器
- from django.contrib.auth.decorators import login_required
- # 局部配置
- @login_required(login_url='/login/')
- # 全局配置
- LOGIN_URL = '/login/'
- 1.如果局部和全局都有 该听谁的?
- 局部 > 全局
- 2.局部和全局哪个好呢?
- 全局的好处在于无需重复写代码 但是跳转的页面却很单一
- 局部的好处在于不同的视图函数在用户没有登陆的情况下可以跳转到不同的页面
-
- # 6.比对原密码
- request.user.check_password(old_password)
-
- # 7.修改密码
- request.user.set_password(new_password) # 仅仅是在修改对象的属性
- request.user.save() # 这一步才是真正的操作数据库
-
- # 8.注销
- auth.logout(request)
-
- # 9.注册
- # 操作auth_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)
如何扩展auth_user表
- # 比如给auth_user表添加一个phone字段,那么该如何扩建呢?
-
- from django.contrib.auth.models import User # auth_user所在的表位置
-
- 我们先来看一下这张表都有那些字段:
- # 所以我们在扩展auth_user表是只需要继承AbstractUser即可
- # 举例:
- # 需导入模块:
- from django.contrib.auth.models import User,AbstractUser
-
- class UserInfo(AbstractUser):
- phone = models.BigIntegerField()
-
- # 需要注意:
- 如果继承了AbstractUser
- 那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了
- 而UserInfo表中会出现auth_user所有的字段外加自己扩展的字段
- 这么做的好处在于我们能够直接点击我们自己的表更加快捷的完成操作以及扩展
-
- - 前提:
- 1、在继承之前没有执行过数据库迁移的命令
- 即auth_user表没有被创建出来,如果当前库已经创建了那么就需要重新创建一个库
- 2、继承的类里面不要覆盖AbstractUser里面的字段名
- 表里面有的字段不要动,只扩展额外的字段即可
- 3、需要再配置文件中告诉django你要用UserInfo代替auth_user
- AUTH_USER_MODEL = 'app01.UserInfo' # 应用名.表名
- 如果自己写表替代了auth_user那么
- auth模块的功能还是照常使用,参考的表由原来的auth_user变成了UserInfo
- # 比如:
- - 原先:
- from django.contrib.auth.models import User
- User.objects.create(username=username,password=password)
-
- - 现在:
- from app01 import models
- models.UserInfo.objects.create(username=username,password=password)
-
- # 方法不变只是操作的表换成了自己指定的表。