十三:Django框架学习之auth模块
什么是auth模块?
auth模块
是django
自带的用户认证模块。
"""
我们在开发一个网站的时候,无可避免的要设计实现用户登录系统。其中,设计到的需求就包括但不限于用户注册,用户登录、用户认证、注销、修改密码等功能。
显而易见,这种重复造轮子的事情,django框架作为一个完美主义者自然会考虑到。它内置了强大的用户认证系统——auth,默认是使用auth_user表来存储用户的数据。
"""
auth模块的常用方法
from django.contrib import auth
authenticate()
验证用户的用户名以及密码是否正确
user_obj = auth.authenticate(
request,
username='username',
password='password',
)
"""
(1)关于参数,括号内必须同时传入用户名以及密码;
(2)数据都符合,返回一个用户对象user_obj,数据不符合则返回None。
"""
login()
保存用户的登录状态信息
该函数接受一个HttpRequest对象,以及一个经过认证的User对象。该函数本质上会在后端为该后端生成相关的session数据。
auth.login(
request,
user_obj,
)
"""
(1)其类视于request.session[key] = user_obj;
(2)执行该方法后,会将user_obj对象封装到request.user中:
print(request.user) # user_obj对象
print(request.user.username) # jason
print(request.user.password) # dbj123
"""
is_authenticated()
用来判断当前的请求是否经过了认证,返回一个布尔值
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL,request.path,))
login_required()
auth 模块提供的登录认证装饰器
from django.contrib.auth.decorators import login_required
# 局部配置
@login_required(login_url='/login/')
# 全局配置
在setiings.py中添加一个全局环境变量
LOGIN_URL = '/login/'
# 局部配置&全局配置
(1)局部配置的优先级要高于全局配置;
(2)全局的好处在于无需写重复的代码,但是跳转的页面单一,
局部的好处是不同的视图函数在用户没有登录的情况下可以跳转到不同的页面。
create_user()
auth提供的创建普通用户的方法,需要提供必要参数username,password
from django.contrib.auth.models import User
user_obj = User.objects.create_user(username='username',password='password',email='email'...)
create_superuser()
auth提供的创建超级用户的方法,需要提供必要参数username,password,email
from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(
username='username',
password='password',
email='email',
)
"""
注意:使用代码创建超级用户的时候必须填邮箱,使用命令行创建超级用户的时候可以不填邮箱。
使用命令行创建超级用户
python manage.py createsuperuser
"""
check_password()
检查用户输入的密码是否正确,返回一个布尔值
is_ok = request.user.check_password(old_password)
set_password()
auth提供的一个修改密码的功能,需要传入新密码作为参数
request.user.set_password(new_password) #仅仅是修改对象的属性
request.user.save() # 这一步才是操作数据库
"""
一定要记得加上save操作
"""
logout()
auth提供的注销功能,该函数接收一个HttpResponse对象,没有返回值。
当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
from django.contrib import auth
def logout(request):
auth.logout(request)
return redirect('/login/')
User对象属性
User对象属性:username,password
is_staff:用户是否有网站的管理权限(是否是管理员)
is_active:是否允许用户登录,设置为False,可以在不删除用户的情况下禁止用户登录
如何扩展auth_user表
- 第一种(一对一关系)
from django.db import models
# 第一种:一对一关系,不推荐
class UserDetail(models.Model):
phone = models.BigIntegerField()
user = models.OneToOneField(to='User')
- 第二种(面向对象的继承)
前提条件
(1)在继承AbstractUser类前,没有执行过数据库迁移命令,即auth_user表没有被创建;
(2)继承的类里面不能覆盖AbstractUser类原有字段名称,只扩展额外的字段即可;
(3)在配置文件settings.py中,告诉django使用User_Info替换auth_user:
AUTH_USER_MODEL = 'app01.UserInfo' # '应用名.表名'
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
GENDER_CHOICE = (
('male', '男'),
('female', '女'),
('secret', '保密'),
)
phone = models.CharField(
max_length=64,
verbose_name='phone',
null=False,
)
age = models.IntegerField(
verbose_name='age',
default=18,
)
gender = models.CharField(
max_length=16,
choices=GENDER_CHOICE,
default='secret',
)
def __str__(self):
return self.username
执行两条数据库迁移命令
python manage.py makemigration
python manage.py migrate
这样auth模块的功能还是能够使用,参考的表由原来的auth_user变成了user_info
使用扩展后的user_info表
- 注册功能
def register(request):
...
is_exists = auth.authenticate(
request,
username=username,
password=password,
)
if is_exists:
return HttpResponse('注册失败,用户已存在!')
user_obj = models.UserInfo.objects.create_superuser(
...
)
return HttpResponse('注册成功!')
- 登录功能
def login(request):
if request.method == 'POST':
...
user_obj = auth.authenticate(
request,
username=username,
password=password,
)
...
auth.login(request, user_obj) # 设置session
return HttpResponse('登录成功!')
return render(request, 'login.html', login_dict)
- home页面
def home(request):
print(request.user) # user_obj对象
print(request.user.is_authenticated()) # 校验用户是否登录
return HttpResponse('home')
加装饰器,然后清除掉session
@login_required(login_url='/login/')
def home(request):
print(request.user)
print(request.user.is_authenticated())
return HttpResponse('home')
- 修改密码功能
@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 == new_password:
# 在校验老密码是否正确
is_right = request.user.check_password(old_password)
if is_right:
# 再修改密码
request.user.set_password(new_password) # 仅仅是修改user_obj对象的属性
request.user.save() # 操作数据库,保存修改
return redirect('/login/')
return HttpResponse('输入的老密码不正确!')
return HttpResponse('两次输入的密码不一致!')
return render(request, 'set_password.html')
- 注销功能
@login_required(login_url='/login/')
def logout(request):
auth.logout(request) # request.session.flush()
return redirect('/login/')