Django
1 auth模块
1.1 介绍
auth模块是认证模块,主要用于管理用户。
auth模块默认使用内置的auth_user表,是Django提供的一张用户表。
当执行数据库迁移命令后会自动创建auth_user表,访问admin路由后进入admin后台管理需要使用auth_user表。
1.2 创建管理员用户(超级用户)
python manage.py createsuperuser
创建后auth_user表中会新增一条管理员用户数据,密码使用SHA256进行加密。
登录管理员账户
http://127.0.0.1:8000/admin/login/?next=/admin/
1.3 功能介绍
1.3.1 登录功能
1.3.1.1 auth.authenticate
auth.authenticate方法,去auth_user表中校验数据。
- 自动查找auth_user表;
- 自动对密码进行加密,再进行比对;
- auth.authenticate方法必须同时传入用户名和密码;
- auth.authenticate方法的返回值是用户对象,如果用户名或密码错误直接返回None。
1.3.1.2 auth.login
auth.login(request, user_obj)方法,去django_session表中保存当前登录用户
- 相当于
request.session['key'] = user_obj
; - auth.login会自动去django_session表中找到当前用户并将其封装到用户对象request.user中,因此执行auth.login后可以在任意位置通过request.user获取当前登录的用户对象;
- 如果未登录直接访问request.user,得到AnonymousUser,即匿名用户对象。
1.3.1.3 request.user.is_authenticated
request.user.is_authenticated()方法,判断当前用户是否登录。
返回True/False。
views.py
from django.shortcuts import render
from django.contrib import auth
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 使用auth模块去auth_user表中校验数据
user_obj = auth.authenticate(
request,
username=username,
password=password
)
print(user_obj.username)
print(user_obj.password) # 加密后的密码
return render(request, 'login.html')
1.3.2 装饰器login_required
装饰器login_required,执行特定功能时必须处于登陆状态。
如果未登录,会默认跳转到/accounts/login/页面,一般需要指定跳转页面。
- 局部配置,为装饰器传入路径参数指定跳转页面;
- 全局配置,修改配置文件
例如登陆后才能访问Home页面。
views.py 局部配置
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
# 装饰器不指定参数,用户未登录时会默认跳转到/accounts/login/。
@login_required
def home1(request):
return render(request, 'home.html')
# 指定用户未登录时跳转的页面,局部配置。
@login_required(login_url='/login/')
def home2(request):
return render(request, 'home.html')
settings.py 全局配置
# 全局配置:用户未登录跳转到指定页面。
LOGIN_URL = '/login/'
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
@login_required
def home1(request):
return render(request, 'home.html')
如果局部配置和全局配置同时存在,以局部配置为准。
1.3.3 修改密码功能
request.user.check_password(password)方法,用于校验密码是否正确。
request.user.set_password()方法,用于设置密码,但仅仅是修改用户对象的属性,不影响数据库。
request.user.save()方法,用于保存数据库。
change_password.html
<form action="" method="post">
{% csrf_token %}
<p>username: <input type="text" name="username" value="{{ request.user.username }} disable"></p>
<p>old password: <input type="password" name="old_password"></p>
<p>new password: <input type="password" name="new_password"></p>
<p>confirm new password: <input type="password" name="confirm_new_password"></p>
<input type="submit">
</form>
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
@login_required(login_url='/login/')
def change_password(request):
if request.method == 'POST':
old_password = request.POST.get('old_password')
new_password = request.POST.get('new_password')
confirm_new_password = request.POST.get('confirm_new_password')
# 校验两次输入的密码是否一致
if new_password != confirm_new_password:
pass
# 校验旧密码是否正确
if request.user.check_password(old_password):
request.user.set_password(new_password) # 仅修改用户对象的属性
request.user.save() # 注意保存数据库
return redirect('/login/')
return render(request, 'change_password.html')
1.3.4 注销功能
auth.logout(request)方法,去django_session表中删除当前登录用户
相当于request.session.flush
。
views.py
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
@login_required(login_url='/login/')
def logout(request):
# 注销
auth.logout(request)
return redirect('/login/')
1.3.5 注册功能
获取user表
from django.contrib.auth.models import User
注意,操作user表创建新用户数据不能使用create方法,因为密码没有经过加密处理。
User.objects.create_user方法,用于创建普通用户。
User.objects.create_superuser方法,用于创建超级用户,邮箱必填。
使用命令行创建超级用户时可以不填邮箱。
register.html
<form action="" method="post">
{% csrf_token %}
<p>username: <input type="text" name="username"></p>
<p>old password: <input type="password" name="old_password"></p>
<p>new password: <input type="password" name="new_password"></p>
<p>confirm new password: <input type="password" name="confirm_new_password"></p>
<input type="submit">
</form>
views.py
from django.contrib.auth.models import User
from django.shortcuts import render
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 操作auth_user表创建新的用户数据
# 操作user表创建新用户数据不能使用create方法,因为密码没有经过加密处理。
# User.objects.create(username=username, password=password)
# 创建普通用户
User.objects.create_user(username=username, password=password)
# 创建超级用户,邮箱必填。
User.objects.create_superuser(username=username, email='test@test.com', password=password)
return render(request, 'register.html')
1.4 auth模块方法总结
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. 注册
from django.contrib.auth.models import User
# 操作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)
2 扩展auth_user表
方式1:利用一对一关系,不推荐
from django.db import models
from django.contrib.auth.models import User
class UserDetail(models.Model):
phone = models.BigIntegerField()
user = models.OneToOneField(to='User')
方式2:利用面向对象的继承方式
如果存在继承了AbstractUser类的自定义类,执行数据库迁移命令时,auth_user表不会自动创建。
继承了AbstractUser类的自定义类对应的自定义表会用于auth_user表中的所有字段和自身扩展的字段。
相当于使用自定义表取代了内置的auth_user表。
注意:
- 使用方式2时没有执行过数据库迁移命令,即没有创建auth_user表。
如果当前库已存在auth_user表,可以考虑换一个库。 - 继承了AbstractUser类的自定义类中不要覆盖AbstractUser类中定义的字段,即只扩展,不修改。
- 需要修改配置文件,声明使用自定义类替换auth_user表,语法:
应用名.表名
。
models.py
from django.contrib.auth.models import AbstractUser
class UserDetail(AbstractUser):
phone = models.BigIntegerField()
settings.py
# '应用名.表名',注意不是路径,中间没有models。
AUTH_USER_MODEL = 'app01.UserDetail'