第十章笔记——Auth认证系统
一般表单类存储到模型的难点在于外键的存在
可用shell来查找问题所在(上上一章遗留,第8章)
CharField也可以写数字,但会自动转换成字符串
Auth认证系统
用户信息: auth_user
用户权限:ayuth_permission
用户组:auth_group
django内置User模型一共定义了11个字段
待补
注册
User模型
# create_user是模型User特有的函数,改函数创建并保存一个is_active=True的User对象,其中username不能为空
写入数据库(使用save()),模型User的其他字段还可作为create_user的可选参数
登录
内置模型authenticate完成账户密码的验证过程
if user.is_active: # is_active字段判断用户是否被激活,is_active为1责备激活
login(request, user) # login()函数接收2个参数,一个是request对象,一个是user对象
修改密码
user.set_password(p2) # 用这个来判断原始密码是否正确么
函数set_password是在内置函数make_password的基础上进行封装而来的。django默认使用pbkdf2_sha256方式存储和管理用户密码,而内置函数make_password用于实现用户密码的加密处理,并且改函数可以脱离Auth认证系统单独使用,比如对某些特殊数据进行加密处理。
使用make_password一般都是先加密密码,然后再user.password=xxx加密后的密码,然后再用save()方法保存到数据库中即可。
内置函数check_password,可对加密前的密码和加密后的密码进行验证匹配,判断两者是否为同一密码。两个参数分别是加密前的密码和加密后的密码。
用户注销,退出登录
def logoutView(request): # request用户请求对象
# logout是内置函数
logout(request) # 这个视图时直接判断,然后跳转么
return HttpResponse('注销成功')
发送邮件实现密码找回
settings.py的配置邮件信息
# 邮件配置信息
EMAIL_USE_SSL = True
# 邮件服务器,如果是 163就改成 smtp.163.com
EMAIL_HOST = 'smtp.qq.com'
# 邮件服务器端口
EMAIL_PORT = 465
# 发送邮件的账号
EMAIL_HOST_USER = 'xxxx@qq.com'
# SMTP服务密码
EMAIL_HOST_PASSWORD = 'dexxxvddfh'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
下方的是基于django后台注册时候填写的邮箱账号为接收账号的
# 找回密码;这里发送邮箱的地址是你注册时候填写的地址
def findpsView(request):
button = '获取验证码'
VCodeInfo = False
password = False
if request.method == 'POST':
u = request.POST.get('username')
VCode = request.POST.get('VCode', '')
p = request.POST.get('password')
user = User.objects.filter(username=u)
# 用户不存在
if not user:
tips = '用户' + u + '不存在'
else:
# 判断验证码是否已发送
if not request.session.get('VCode', ''):
# 发送验证码并将验证码写入session
button = '重置密码'
tips = '验证码已发送'
password = True
VCodeInfo = True
VCode = str(random.randint(1000, 9999)) # 随机生成长度为4的验证码
# 会话session
request.session['VCode'] = VCode # 写入会话Session的VCode,其作用是与用户输入的验证码进行匹配
# email_user函数发送验证密码;模型User特有的方法
user[0].email_user('找回密码', VCode) #发送邮件的方式email_user
# 匹配输入的验证码是否正确,发送完毕之后爱匹配,可写在if之后
elif VCode == request.session.get('VCode'):
# 密码加密处理并保存到数据库
dj_ps = make_password(p, None, 'pbkdf2_sha256') # p是你输入的密码
user[0].password = dj_ps # 利用加密处理重置就可以保存密码了
user[0].save()
del request.session['VCode']
tips = '密码已重置'
# 输入验证码错误
else:
tips = '验证码错误,请重新获取'
VCodeInfo = False
password = False
del request.session['VCode']
return render(request, 'user.html', locals())
除了使用内置函数email_user发送邮件(模型User的),其他方式
待补
### send_mass_mail
### EmailMultiAlternatives
用shell来发送邮件
应该只能发送一个管理员注册时候的账号,若通过DEFAULT_FROM_EMAIL
DEFAULT_FROM_EMAIL
默认: 'webmaster@localhost'
用于来自站点管理员的各种自动通信的默认电子邮件地址。这不包括发送到ADMINS 和的错误消息MANAGERS;为此,请参阅SERVER_EMAIL。
In [1]: from django.core.mail import send_mail
In [2]: from django.conf import settings
In [3]: from_email = settings.DEFAULT_FROM_EMAIL
In [4]: sending = ['xxx@qq.com']
In [5]: send_mail('django_test','打扰',from_email,sending)
User模型的扩展与使用
django提供了4种模型扩展扩展的方法
代理模型:
一种模式继承,这种模型在数据库种无需创建新数据表。一般用于改变现有模型的行为方式,如增加新方法函数等,并且不影响数据表的结构。如果不需要在数据表存储额外的信息,只是增加模型User的操作方法或更改模型的查询方式,那么可以使用代理模型扩展模型User.
Profile扩展模型User":
待补
AbstractBaseUser扩展。。。
待补
AbstractUser扩展。。。
待补
User的源文件
django/contrib/auth/models.py
模型User继承自AbstractUser
class User(AbstractUser):
pass
而AbstractUser继承自AbstractBaseUser和PermissionsMixin
class AbstractUser(AbstractBaseUser, PermissionsMixin):
pass
模型User的字段和方法是由父类AbstractUser,AbstractBaseUser和PermissionsMixin定义的。
使用AbstractUser来扩展User
自定义表单类来实现模型绑定在后台页面上;
from django.contrib.auth.forms import UserCreationForm
from .models import MyUser
这个需要好好研究,在书本的第255页
class MyUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = MyUser
# 在注册界面添加邮箱、手机号码、微信号码和QQ号码
fields = UserCreationForm.Meta.fields
fields += ('email', 'mobile', 'weChat', 'qq')
权限的设置与使用
在后台管理界面中每个权限以
'项目应用|模型|模型使用权限'的格式展现
设置用户权限实际上是对数据表user_myuser(自定义User类的实例数据表,和auth_user数据表等价)和auth_permission之间的数据设置多对多关系
用户、用户组、权限三者关系
无论是设置用户权限,设置用户所属用户组或者设置用户组的权限,他们的本质都是对两个数据表之间的数据建立多对多的数据关系,说明如下:(auth_user是下方的user_myuser)
数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,设置用户所拥有的权限
数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,设置用户所在的用户组
数据表auth_group_permissions:管理数据表auth_group和数据表auth_permission之间的多对多关系,设置用户组所在的权限。
用django的shell模式实现用户权限设置
未整理,观感欠佳
In [1]: from user.models import MyUser
In [2]: user = MyUser.objects.filter(username='xinbancan')
In [3]: #
In [4]: # 判断当前用户是否具有用户新增的权限
In [5]: # user.add_myuser为固定写法
In [6]: user为项目应用的名称
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-1b175a0fa344> in <module>
----> 1 user为项目应用的名称
NameError: name 'user为项目应用的名称' is not defined
In [7]: # add_myuser来自数据表auth_permission的字段codename
In [8]: user.has_perm('user.add_myuser')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-f956f40c0fc8> in <module>
----> 1 user.has_perm('user.add_myuser')
AttributeError: 'QuerySet' object has no attribute 'has_perm'
In [9]: # 直接报错,缘由它的权限为空
In [10]: # 导入模型Permission
In [11]: from django.contrib.auth.models import permission
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-11-ee3691ae7171> in <module>
----> 1 from django.contrib.auth.models import permission
ImportError: cannot import name 'permission'
In [12]: from django.contrib.auth.models import Permission
In [13]: # 在权限管理表获取权限add_myuser的数据对象permission
In [14]: p = Permission.objects.filte(codename='add_group')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-14-e760cdecd143> in <module>
----> 1 p = Permission.objects.filte(codename='add_group')
AttributeError: 'PermissionManager' object has no attribute 'filte'
In [15]: p = Permission.objects.filter(codename='add_group')
In [16]: # 对当前用户对象user设置权限add_myuser
In [17]: # 该字段由内置模型User的父类PermissionsMixin定义
In [18]: p = Permission.objects.filter(codename='add_myuser')
In [19]: user.user_permissions.add(p)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-19-62527e976675> in <module>
----> 1 user.user_permissions.add(p)
AttributeError: 'QuerySet' object has no attribute 'user_permissions'
In [20]: user = MyUser.objects.filter(username='xinbancan1')
In [21]: user.user_permissions.add(p)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-21-62527e976675> in <module>
----> 1 user.user_permissions.add(p)
AttributeError: 'QuerySet' object has no attribute 'user_permissions'
In [22]: # 总之这个就是你没有权限,我用shell把该权限提取出来,然后赋值给你
自定义用户权限
在models.py中设定
class Meta(AbstractUser.Meta):# 这章是为了自定义用户权限
# 自定义权限
permissions = ( # 元组或列表形式展示,元组或列表的每个元素代表一个权限,每个权限以元组或列表表示
('vip_myuser', 'Can vip user'), # 把这个权限加入到和增删改查同级别权限么
) # 一个权限种含有两个元素,分别表示数据表auth_permission的codename字段和name字段
设置用户的访问权限
就是设定一个登录界面在跳转么,采用装饰器判断用户在页面跳转的时候是否符合下一个页面的条件,那这里肯定采用了session,他在哪呢
# login_required判断用户是否已登录。
# permission_required判断当前用户是否具备某个权限
@login_required(login_url='/login.html')
@permission_required(perm='user.vip_myuser', login_url='/login.html')
def infoView(request):
return render(request, 'info.html', locals())
上述两个函数作用及参数
# login_required判断用户是否已登录。无登录,则跳转到登录界面
# 4个参数,function,默认值为None,这是定义装饰器的执行函数;redirect_field_name:默认值是next,当登录成功后,程序会自动跳回之前浏览的网页
# login_url:设置用户登录的路由地址,默认值是settings.py中的配置属性,而配置属性LOGIN_URL需要开发者自行配置
# permission_required判断当前用户是否具备某个权限
# 参数perm:必选参数,判断当前用户是否具备某个权限;参数login_url为设置验证失败之后的跳转路由,默认值为None,若不设置,则跳转失败后会抛出404异常
# raise_exception:设置抛出异常,默认值为False
django解析模板文件自动生成的模型变量user和perms
变量user和perms分别是用户和权限表单,即auth_user(自定义用户管理则是其他表单),auth_permission
有时候视图函数中并没有定义变量,但有些变量是可以在Django解析模板文件的过程中生成的,他们与配置文件settings.py文件的Templates设置有关;这里的auth就是内置模型User。若你设置了自定义用户管理,也就是导入了这个模块,那么你的models.py在实例化时会生成这两个变量,即数据表的实例化
'OPTIONS': {
'context_processors': [ # 处理器集合
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', # 运到到auth程序时,会生成变量user和perms,并将变量传入模板上下文TemplateContext中
'django.contrib.messages.context_processors.messages',
],
用户组的设置与使用
用户组是对用户进行分组管理,其作用是在权限控制中可以批量的对用户权限进行分配,无需将权限一个一个分配到每个用户,节省维护的工作量。将用户加入某个用户组,该用户就拥有该用户组所具备的权限。
用户组看可以理解为用户和权限之间的中转站。
设置用户组分为两个步骤,设置用户组的权限和设置用户组的用户。
对用户组进行权限分配
In [1]: # 用户组的权限配置
In [2]: # 导入内置模型Group和Permission
In [3]: from django.contrib.auth.models import Group
In [4]: from django.contrib.auth.models import Permission
In [5]: # 内置的auth表名开头都大写,去表auth
In [6]: # 获取权限对象p
In [7]: p = Permission.objects.get(codename='vip_myuser')
In [8]: # 获取某个用户组group
In [9]: group = Group.objects.get(id=1)
In [10]: # 将权限对象P添加到用户组group中
In [11]: group.permissions.add(p)
# 在auth_group_permissions表中就会生成如下的数据表
"id" "group_id" "permission_id" "NAVICAT_ROWID"
"1" "1" "25" "1"
# 删除当前用户组group的vip_myuser权限
group.permissions.remove(p)
# 在auth_group_permissions表下生成的数据就会消失
In [13]: # 删除当前用户组group的全部权限
In [14]: group.permissions.clear()
实现用户组的用户分配
这个过程是对auth_group和user_myuser构建多对多的数据关系,数据关系保存在数据表user_myuser_groups中。
In [15]: # 导入模型Group和MyUser
In [16]: from user.models import MyUser
In [17]: from django.contrib.auth.models import Group
In [18]: # 获取用户对象user,代表用户名为user1的数据信息
In [19]: user = MyUser.objects.get(username='user1')
In [20]: # 获取用户组group
In [21]: group = Group.objects.get(id=1)
In [22]: # 将用户添加到用户组
In [23]: user.groups.add(group)
In [24]: # 删除用户组某用户
In [25]: user.groups.remove(group)
In [26]: # 删除用户组全部用户
In [27]: user.groups.clear()
笔记来源:Django Web应用开发实战