玩转Django2.0---Django笔记建站基础九(二)
作者:互联网
9.4 设置用户权限
用户权限主要是对不同的用户设置不同的功能使用权限,而每个功能主要以模型来划分。以9.3节的MyDjango项目为例,在Admin后台管理系统可以查看并设置用户权限,如下图:
用户权限设置
上图左边列表框中列出了整个项目的用户权限,以user|用户|Can add user为例:
1、user代表项目的App。
2、用户代表App所定义的模型MyUser。
3、Can add user代表该权限可对模型MyUser执行新增操作。
一般情况下,在执行数据迁移时,每个模型默认拥有增(add), 改(change),删(delete)权限。数据迁移完成后,可以在数据库中查看数据表auth_permission的数据信息,每条数据信息代表项目中某个模型的某个权限,如下图:
设置用户权限实质上是对数据表user_myuser和auth_permission之间的数据设置多对多关系。首先需要了解用户、用户权限和用户组三者之间的关系,以MyDjango的数据表为例,如下图:
从整个项目的数据表可以看到,用户、用户权限和用户组分别对应数据表user_myuser、auth_permission和auth_group。无论是设置用户权限、设置用户所属用户组还是设置用户组的权限,其实质都是对两个数据表之间的数据建立多对多的数据关系,说明如下:
1、数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,实现用户权限设置。
2、数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,实现在用户组设置用户。
3、数据表auth_group_permissions:管理数据表auth_group和auth_permission之间的多对多关系,实现用户组设置权限。
实现用户的权限设置需要注意:如贵哦用户角色是超级用户,该用户是无须设置权限的,用户权限只适用于非超级用户。我们在PyCharm的Terminal下开启Django的shell模式来实现用户权限设置,代码如下:
(py3_3) E:\test5\MyDjango>python manage.py shell #导入模型MyUser In [1]: from user.models import MyUser #查询用户信息,filter查询返回列表格式,因此设置列表索引获取User对象 In [3]: user = MyUser.objects.filter(username='user1')[0] #判断当前用户是否具有权限add_product #index.add_product为固定写法,index为项目的App名,add_product是数据表auth_permission的字段codename In [4]: user.has_perm('index.add_product') Out[4]: False #导入模型Permission In [5]: from django.contrib.auth.models import Permission #在权限管理表获取权限add_product的数据对象permission In [7]: permission = Permission.objects.filter(codename='add_product')[0] #对当前用户对象user设置权限add_product In [10]: user.user_permissions.add(permission) #再次判断当前用户是否具有权限add_product In [12]: user.has_perm('index.add_product') Out[12]: True
上述代码对用户名为user1的用户设置了产品信息的新增权限,打开数据表user_myuser_user_permissions可以看到新增了一条数据,如下图:
数据表user_myuser_user_permissions
数据表的字段myuser_id和permission_id分别是数据表user_myuser和auth_permission的主键,如上图上的每一条数据代表某个用户具有某个模型的某个操作权限。除了添加权限之外,还可以对用户的权限进行删除和查询,代码如下:
In [6]: user = MyUser.objects.filter(username='user1')[0] In [10]: permission = Permission.objects.filter(codename='add_product')[0] #删除某条权限 In [11]: user.user_permissions.remove(permission) #判断是否已删除权限,若为False,说明删除成功。函数has_perm用于判断用户是否拥有权限 In [12]: user.has_perm('index.add_product') Out[12]: False #清空当前用户全部权限 In [13]: user.user_permissions.clear() #获取当前用户所拥有的权限信息 #将上述删除的权限添加到数据表再查询 In [14]: user.user_permissions.add(permission) In [15]: user.user_permissions.values() Out[15]: <QuerySet [{'id': 25, 'name': 'Can add product', 'content_type_id': 7, 'codename': 'add_product'}]>
9.5 自定义用户权限
一般情况下,每个模型默认拥有增(add),改(change),删(delete)权限。但实际开发中,可能要对某个模型设置特殊的权限,比如设置访问权限。为了解决这种情况,在定义模型的时候,可以在模型的Meta中设置自定义权限。以MyDjango为例,对index的模型Product重新定义,代码如下:
#index/models.py class Product(models.Model): id = models.AutoField('序号', primary_key=True) name = models.CharField('名称',max_length=50) weight = models.CharField('重量',max_length=20) size = models.CharField('尺寸',max_length=20) type = models.ForeignKey(Type, on_delete=models.CASCADE,verbose_name='产品类型') # 设置返回值 def __str__(self): return self.name class Meta: #自定义权限 permissions = ( ('visit_Product', 'Can visit Product'), )
定义模型Product的时候,通过重写父类models.Model的permissions属性可实现自定义用户权限。该属性以元组或列表的数据格式表示,每个元素代表一个权限,也是以元组或列表表示。在一个权限中含有两个元素,如('add_Product', 'Can create Product'),add_product和Can create Product分别是数据表auth_permission的codename和name字段。
在数据库中清除MyDjango原有的数据表,并在PyCharm的Terminal中重新执行数据迁移,指令代码如下:
(py3_3) E:\test5\MyDjango>python manage.py makemigrations (py3_3) E:\test5\MyDjango>python manage.py migrate
指令执行完成后,在数据库中打开数据表auth_permission,可以找到自定义权限visit_Product,如下图:
自定义全visit_Product截图
9.6 设置网页的访问权限
本节中,结合实际的例子讲述如何在实际开发中使用用户权限,以MyDjango为例,数据表auth_permission已自定义权限visit_Product,数据表user_myuser分别创建了一名超级用户和一名普通用户,如下图:
数据表user_myuser的用户信息
本例需要将项目的index和user结合使用。index主要将权限应用到开发中,而user主要用于用户的注册、登录和退出登录,用于检验index的应用效果。
首先讲解user的开发流程,我们分别对路由urls.py、视图views.py和模板user.html进行相应开发,共同完成用户的注册、登录和退出登录,代码如下:
#路由user/urls.py from django.urls import path from . import views urlpatterns = [ #用户登录 path('login.html', views.loginView, name='login'), #用户注册 path('register.html', views.registerView, name='register'), #退出登录 path('logout.html', views.logoutView, name='logout'), ] #视图user/views.py from django.shortcuts import render, redirect from .models import MyUser from django.contrib.auth.models import Permission from django.contrib.auth import login, authenticate, logout # 用户登录 def loginView(request): tips = '请登录' title = '用户登录' if request.method == 'POST': username = request.POST.get('username', '') password = request.POST.get('password', '') if MyUser.objects.filter(username=username): user = authenticate(username=username, password=password) if user: if user.is_active: # 登录当前用户 login(request, user) return redirect('/') else: tips = '账号密码错误,请重新输入' else: tips = '用户不存在,请注册' return render(request, 'user.html', locals()) # 用户注册 def registerView(request): title = '用户注册' if request.method == 'POST': username = request.POST.get('username', '') password = request.POST.get('password', '') if MyUser.objects.filter(username=username): tips = '用户已存在' else: user = MyUser.objects.create_user(username=username, password=password) user.save() # 添加权限 permission = Permission.objects.filter(codename='visit_Product')[0] user.user_permissions.add(permission) return redirect('/user/login.html') return render(request, 'user.html', locals()) # 退出登录 def logoutView(request): logout(request) return redirect('/')
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <title>{{ title }}</title> <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css"> </head> <body> <div class="flex-center"> <div class="container"> <div class="flex-center"> <div class="unit-1-2 unit-1-on-mobile"> <h1>MyDjango Auth</h1> {% if tips %} <div>{{ tips }}</div> {% endif %} <form class="form" action="" method="post"> {% csrf_token %} <div>用户名:<input type="text" name='username'></div> <div>密 码:<input type="password" name='password'></div> <button type="submit" class="btn btn-primary btn-block">确定</button> </form> </div> </div> </div> </div> </body> </html>
上述代码主要实现一个简单的操作流程,流程顺序为用户注册->用户登录->访问首页,具体实现过程如下:
1、首先用户访问用户注册界面,输入新的用户信息并单击"确定"按钮,提交用户注册信息到网站后台。
2、后台的视图函数registerView接收表单数据,判断当前注册的用户是否存在。如果用户不存在,将表单数据保存到数据表user_myuser中,创建新的用户信息。
3、默认情况下,新创建的用户是没有设置任何权限的,视图函数对新创建的用户设置visit_Product权限。注册成功后,程序会自动跳转到用户登录界面。
4、在用户登录界面输入新创建的用户信息,完成用户登录后,程序会自动跳转到网站的首页。
在user中实现了用户的权限设置,为新创建的用户添加visit_Product权限,接着在index中实现用户权限的校验。在index的路由urls.py、视图views.py和模板index.html中分别编写以下代码:
#index/urls.py from django.urls import path from . import views urlpatterns = [ # 首页的URL path('', views.index), ] #index/views.py from django.shortcuts import render from django.contrib.auth.decorators import login_required, permission_required # 使用login_required和permission_required分别对用户登录验证和用户权限验证 @login_required(login_url='/user/login.html') @permission_required(perm='index.visit_Product', login_url='/user/login.html') def index(request): return render(request, 'index.html', locals())
在视图函数index中使用了装饰器login_required和permission_required,分别对当前用户的登录状态和用户权限进行校验,说明如下:
login_required:设置用户登录访问权限。如果当前用户尚未在用户登录界面完成登录而直接访问首页,程序自动跳转到登录界面,只有用户完成登录后才能访问首页。login_required的参数有redirect_field_name和login_url。
1、参数redirect_field_name:默认值是next。当登录成功之后,程序会自动跳回之前浏览的网页。
2、参数login_url:设置登录界面的URL地址。默认值是settings.py的属性LOGIN_URL,而属性LOGIN_URL需要开发者自行在settings.py中配置。
permission_required:验证当前用户是否拥有相应的权限。若用户没有使用权限,程序会跳转到登录界面或者抛出异常。permission_required的参数如下。
1、参数perm:必须参数,判断当前用户是否拥有权限。参数值为固定格式,如index.visit_Product,index为项目的App名,visit_product来自数据表auth_permission的字段codename。
2、参数login_url:设置登录界面的URL地址,默认值为None。若不设置参数,验证失败后会抛出404异常。
3、参数raise_exception:设置抛出异常,默认值为False。
装饰器permission_required的作用与内置函数has_perm相同,上述代码也可以使用函数has_perm实现装饰器permission_required的功能,代码如下:
#使用函数has_perm实现装饰器permission_required功能 from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required @login_required(login_url='/user/login.html') def index(request): user = request.user if user.has_perm('index.visit_Product'): return render(request, 'index.html', locals()) else: return redirect('/user/login.html')
最后在模板index.html中实现用户权限判断,这也是权限校验的使用方法之一。模板index.html的<header>标签代码修改如下:
<header id="top"> <!-- 内容显示区域 :width : 1211px --> <div id="top_box"> <ul class="lf"> <li><a href="#">华为官网</a></li> <li><a href="#">华为荣耀</a></li> </ul> <ul class="rt"> {#在模版中使用user变量是一个User或者AnoymousUser对象,该对象由模型MyUser实例化#} {% if user.is_authenticated %} <li>用户名: {{ user.username }}</li> <li><a href="{% url 'logout' %}">退出登录</a></li> {% endif %} {#在模版中使用perms变量是Permission对象,该对象由模型Permission实例化#} {% if perms.index.add_product %} <li>添加产品信息</li> {% endif %} </ul> </div> </header>
在模板index.html中分别使用变量user和perms,但从视图函数index总可以发现,视图函数并没有将变量user和perms传递给模板。其实变量user和perms是由Django自动生成的,变量的生成与配置五年级settings.py的TEMPLATES设置有关,我们查看setting.py的TEMPLATES配置信息,代码如下:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'index/templates'), os.path.join(BASE_DIR, 'user/templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
因为TEMPLATES中定义了处理器集合context_processors,所以在解析模板Template之前,Django首先依次运行处理器集合的程序。当运行到处理器django.contrib.auth.context_processors.auth时,程序会生成变量user和perms,并且将变量传入模板变量TemplateContext中,所以在模板中可以直接使用变量user和perms。
从上述例子可以看到,项目的user主要实现权限的设置功能;项目的index主要实现权限的使用,权限的使用主要判断当前用户是否具有权限的使用资格,而权限的判断可以从视图函数或模板语法实现。在浏览器上分别使用超级用户和普通用户登录网站,两者的首页信息如下图:
9.7 设置用户组
顾明思义,用户组就是对用户进行分组管理,其作用是在权限控制中可以批量地对用户的权限进行分配,而不同一个一个地按用户组所分配的所有权限。例如用户组teachers拥有权限can_create_lesson,那么所有属于teachers的用户都会有can_create_lesson权限。
我们知道用户、权限和用户组三者之间是多对多的数据关系,而用户组可以理解为用户和权限之间的中转站。设置用户组分为两个步骤:设置用户组的权限和设置用户组的用户。
设置用户组的权限主要对数据表auth_group和auth_permission构建多对多的数据关系,数据关系保存在数据表auth_group_permissions中。以MyDjango为例,其数据库结构如下图所示:
数据库结构
在数据表auth_group中创建三条数据信息:产品信息、产品类型和用户管理,每条信息在项目中代表一个用户组,如下图:
数据表auth_group
我们在PyCharm的Terminal中使用Django的shell模式来实现用户组的权限配置,代码如下:
#用户组的权限配置 #导入内置模型Group和Permission (py3_3) E:\test5\MyDjango>python manage.py shell In [1]: from django.contrib.auth.models import Group In [2]: from django.contrib.auth.models import Permission #获取某个权限对象permission In [3]: permission = Permission.objects.get(codename='visit_Product') #获取某个用户组对象group In [4]: group = Group.objects.get(id=1) #将权限permission添加到用户组group中 In [5]: group.permissions.add(permission)
上述代码将visit_Product权限添加到用户组(产品信息),功能实现过程如下:
1、从数据表auth_group获取用户组(产品信息)对象group,对象group代表数据表总某一条数据。
2、从数据表auth_permission获取权限(visit_Product)对象permission,对象permission代表数据表中某一条数据。
3、使用permissions.add方法将权限对象permission与用户组对象group构建多对多数据关系并保存在数据表auth_group_permissions中。查看数据表auth_group_permissions,数据信息如下图:
数据表auth_group_permissions
除了添加用户组的权限之外,还可以删除用户组已有的权限,代码如下:
#删除当前用户组group的visit_Product权限 In [6]: group.permissions.remove(permission) #删除当前用户组group的全部权限 In [7]: group.permissions.clear()
设置用户组的用户主要对数据表auth_group和user_myuser构建多对多数据关系,数据关系保存在数据表user_myuser_groups中。在Django的shell模式下实现用户组的用户设置,代码如下:
#将用户分配到用户组 #导入模型Group和MyUser In [8]: from user.models import MyUser In [9]: from django.contrib.auth.models import Group #获取用户对象user,对象user代表用户名为user1的数据信息 In [11]: user = MyUser.objects.get(username='user1') #获取用户组对象group,对象group代表用户组(产品信息)的数据信息 In [13]: group = Group.objects.get(id=1) #将用户添加到用户组 In [14]: user.groups.add(group)
上述代码将用户名为user1的用户添加到用户组(产品信息),功能实现过程与用户组的权限设置是相似的,只不过两者所使用的模型有所不同。查看数据表user_myuser_groups,数据信息如下图:
数据表user_myuser_groups
除了添加用户组的用户之外,还可以删除用户组已有的用户,代码如下:
#删除用户组某一用户 In [15]: user.groups.remove(group) #情况用户组全部用户 In [16]: user.groups.clear()
9.8 本章小结
Django除了有强大的Admin管理系统之外,还提供了完善的用户管理系统。整个用户管理系统可分为三大部分:用户信息、用户权限和用户组,在数据库中分别对应数据表auth_user、auth_permission和auth_group。
使用内置模型User和内置的函数可以快速实现用户管理功能,如用户注册、登录、密码修改、密码找回和用户注销。模型User的字段说明以及常用的内置函数如下。
模型User字段及说明
字段 | 说明 |
ID | int类型,数据表主键 |
Password | varchar类型,代表用户密码,在默认情况下使用pbkdf2_sha256方式来存储和管理用户的密码 |
last_login | datetime类型,最近一次登录的时间 |
is_superuser | tinyint类型,表示该用户是否拥有所有的权限,即是否为超级用户 |
Username | varchar类型,代表用户账号 |
first_name | varchar类型,代表用户的名字 |
last_name | varchar类型,代表用户的姓氏 |
varchar类型,代表用户的邮件 | |
is_staff | 用来判断用户是否可以登录进入Admin系统 |
is_active | tinyint类型,用来判断该账户的状态是否被激活 |
date_joined | datetime类型,账号的创建时间 |
常用的内置函数及说明
内置函数 | 说明 |
authenticate | 验证用户是否存在,必选参数为username和password,只能用于模型User |
create_user | 创建新的用户信息,必选参数为username,只能用于模型User |
set_password | 修改用户密码,必选参数为password,只能用于模型User |
login/logout | 用户的登录和注销,只能哟农户模型User |
make_password | 密码加密处理,必选参数为password,可脱离模型User单独使用 |
check_password | 检验加密前后的密码是否相同,可脱离模型User单独使用 |
email_user | 发送邮件,只能用于模型User |
send_mail | 发送邮件 |
send_mass_mail | 批量发送邮件 |
EmailMultiAlternatives | 发送自定义内容格式的邮件 |
Django提供了4中模型扩展的方法:
1、代理模型:这是一种模型继承,这种模型在数据库中无须创建新数据表。一般用于改变现有模型的行为方式,如增加新方法函数等,并且不影响现有数据库的结构。当不需要在数据库中存储额外的信息,而需要增加操作方法或更改模型的查询管理方式时,适合使用代理模型来扩展现有User模型。
2、Profile扩展模型User:当存储的信息与模型User相关,而且并不改变模型User原有的认证方法时,可定义新的模型MyUser,并设置某个字段为OneToOneField,这样能与模型User形成一对一关联,该方法称为用户配置(User Profile)。
3、AbstractBaseUser扩展模型User:当模型User的内置方法并不符合开发需求时,可使用该方法对模型User重新自定义设计,该方法对模型User和数据库架构影响很大。
4、AbstractUser扩展模型User:如果模型User的内置的方法符合开发需求,在不改变这些函数方法的情况下,添加模型User的额外字段,可通过AbstractUser方式实现。使用AbstractUser定义的模型会替换原有模型User。
用户、用户权限和用户组分别对应数据表user_myuser、auth_permission和auth_group。无论是设置用户权限、设置用户所属用户组还是设置用户组的权限,其实质都是对两个数据表之间的数据建立多对多的数据关系,说明如下:
1、数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,实现用户权限设置。
2、数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,实现在用户组设置用户。
3、数据表auth_group_permissions:管理数据表auth_group和auth_permission之间的多对多关系,实现用户组设置权限。
标签:Django2.0,用户组,用户,auth,Django,数据表,user,权限,玩转 来源: https://www.cnblogs.com/zhaop8078/p/11603404.html