博客
关于我
Django基础(23): 权限管理(permissions)与用户组(group)详解
阅读量:234 次
发布时间:2019-02-28

本文共 6007 字,大约阅读时间需要 20 分钟。

如果你只是利用Django开发个博客,大部分用户只是阅读你的文章而已,你可能根本用不到本节内容。但是如果你想开发一个内容管理系统,或用户管理系统,你必需对用户的权限进行管理和控制。Django自带的权限机制(permissions)与用户组(group)可以让我们很方便地对用户权限进行管理。小编我今天就尝试以浅显的语言来讲解下如何使用Django自带的权限管理机制。

 

什么是权限?

 

权限是能够约束用户行为和控制页面显示内容的一种机制。一个完整的权限应该包含3个要素: 用户,对象和权限,即什么用户对什么对象有什么样的权限。

 

假设我们有一个应用叫blog,其包含一个叫Article(文章)的模型。那么一个超级用户一般会有如下4种权限,而一个普通用户可能只有1种或某几种权限,比如只能查看文章,或者能查看和创建文章但是不能修改和删除。

 

  • 查看文章(view)

  • 创建文章(add)

  • 更改文章(change)

  • 删除文章(delete) 

 

我们在Django的admin中是可以很轻易地给用户分配权限的。

 

Django Admin中的权限分配

 

Django中的用户权限分配,主要通过Django自带的Admin界面进行维护的。当你编辑某个user信息时, 你可以很轻易地在User permissions栏为其设置对某些模型查看, 增加、更改和删除的权限(如下图所示)。

Django的权限permission本质是djang.contrib.auth中的一个模型, 其与User的user_permissions字段是多对多的关系。当我们在INSTALLED_APP里添加好auth应用之后,Django就会为每一个你安装的app中的模型(Model)自动创建4个可选的权限:view, add,change和delete。(注: Django 2.0前没有view权限)。随后你可以通过admin将这些权限分配给不同用户。

 

查看用户的权限

 

权限名一般有app名(app_label),权限动作和模型名组成。以blog应用为例,Django为Article模型自动创建的4个可选权限名分别为:

  • 查看文章(view): blog.view_article

  • 创建文章(add): blog.add_article

  • 更改文章(change): blog.change_article

  • 删除文章(delete): blog.delete_article

 

在前例中,我们已经通过Admin给用户A(user_A)分配了创建文章和修改文章的权限。我们现在可以使用user.has_perm()方法来判断用户是否已经拥有相应权限。下例中应该返回True。

  • user_A.has_perm('blog.add_article')

  • user_A.has_perm('blog.change_article')

 

如果我们要查看某个用户所在用户组的权限或某个用户的所有权限(包括从用户组获得的权限),我们可以使用get_group_permissions()和get_all_permissions()方法。

  • user_A.get_group_permissions()

  • user_A.get_all_permissions()

 

手动定义和分配权限(Permissions)

 

有时django创建的4种可选权限满足不了我们的要求,这时我们需要自定义权限。实现方法主要有两种。下面我们将分别使用2种方法给Article模型新增了两个权限,一个是publish_article, 一个是comment_article。

 

方法1. 在Model的meta属性中添加permissions。

class Article(models.Model):    ...    class Meta:        permissions = (            ("publish_article", "Can publish article"),            ("comment_article", "Can comment article"),        )

 

方法2. 使用ContentType程序化创建permissions。

from blog.models import Articlefrom django.contrib.auth.models import Permissionfrom django.contrib.contenttypes.models import ContentTypecontent_type = ContentType.objects.get_for_model(article)permission1 = Permission.objects.create(    codename='publish_article',    name='Can publish articles',    content_type=content_type,)permission2 = Permission.objects.create(    codename='comment_article',    name='Can comment articles',    content_type=content_type,)

当你使用python manage.py migrate命令后,你会发现Django admin的user permissions栏又多了两个可选权限。

 

如果你不希望总是通过admin来给用户设置权限,你还可以在代码里手动给用户分配权限。这里也有两种实现方法。

 

方法1. 使用user.user_permissions.add()方法

myuser.user_permissions.add(permission1, permission2, ...)

 

方法2. 通过user所在的用户组(group)给用户增加权限

mygroup.permissions.add(permission1, permission2, ...)

 

如果你希望在代码中移除一个用户的权限,你可以使用remove或clear方法。

myuser.user_permissions.remove(permission, permission, ...)myuser.user_permissions.clear()

 

注意权限的缓存机制

 

Django会缓存每个用户对象,包括其权限user_permissions。当你在代码中手动改变一个用户的权限后,你必须重新获取该用户对象,才能获取最新的权限。

 

比如下例在代码中给用户手动增加了change_blogpost的权限,如果不重新载入用户,那么将显示用户还是没有change_blogpost的权限。

from django.contrib.auth.models import Permission, Userfrom django.contrib.contenttypes.models import ContentTypefrom django.shortcuts import get_object_or_404from myapp.models import BlogPostdef user_gains_perms(request, user_id):    user = get_object_or_404(User, pk=user_id)    # any permission check will cache the current set of permissions    user.has_perm('myapp.change_blogpost')     content_type = ContentType.objects.get_for_model(BlogPost)    permission = Permission.objects.get(        codename='change_blogpost',        content_type=content_type,    )    user.user_permissions.add(permission)    # Checking the cached permission set    user.has_perm('myapp.change_blogpost')  # False    # Request new instance of User    # Be aware that user.refresh_from_db() won't clear the cache.    user = get_object_or_404(User, pk=user_id)    # Permission cache is repopulated from the database    user.has_perm('myapp.change_blogpost')  # True

 

用户权限的验证(Validation)

 

我们前面讲解了用户权限的创建和设置,现在我们将进入关键一环,用户权限的验证。我们在分配好权限后,我们还需要在视图views.py和模板里验证用户是否具有相应的权限,否则前面设置的权限形同虚设。这就是为什么我们前面很多django实战案例里,没有给用户分配某个模型的add和change权限,用户还是还能创建和编辑对象的原因。

 

1. 视图中验证

在视图中你当然可以使用user.has_perm方法对一个用户的权限进行直接验证。当然一个更好的方法是使用@permission_required这个装饰器。

permission_required(permlogin_url=Noneraise_exception=False)

你如果指定了login_url, 用户会被要求先登录。如果你设置了raise_exception=True, 会直接返回403无权限的错误,而不会跳转到登录页面。使用方法如下所示:

from django.contrib.auth.decorators import permission_required@permission_required('polls.can_vote')def my_view(request):    ...

如果你使用基于类的视图(Class Based View), 而不是函数视图,你需要继承PermissionRequiredMixin这个类,如下所示:

from django.contrib.auth.mixins import PermissionRequiredMixinclass MyView(PermissionRequiredMixin, View):    permission_required = 'polls.can_vote'    # Or multiple of permissions:    permission_required = ('polls.can_open', 'polls.can_edit')

 

2. 模板中验证

在模板中验证用户权限主要需要学会使用perms这个全局变量。perms对当前用户的user.has_module_perms和user.has_perm方法进行了封装。当我们需要判断当前用户是否拥有blog应用下的所有权限时,我们可以使用:

{  { perms.blog }}

 

我们如果判断当前用户是否拥有blog应用下发表文章讨论的权限,则使用:

{  { perms.blog.comment_article }}

这样结合template的if标签,我们可以通过判断当前用户所具有的权限,显示不同的内容了.

{% if blog.article %}    

You have permission to do something in this blog app.

   {% if perms.blog.add_article %}        

You can add articles.

   {% endif %}    {% if perms.blog.comment_article %}        

You can comment articles!

   {% endif %}{% else %}    

You don't have permission to do anything in the blog app.

{% endif %}

 

用户组(Group)

 

用户组(Group)和User模型是多对多的关系。其作用在权限控制时可以批量对用户的权限进行管理和分配,而不用一个一个用户分配,节省工作量。将一个用户加入到一个Group中后,该用户就拥有了该Group所分配的所有权限。例如,如果一个用户组editors有权限change_article, 那么所有属于editors组的用户都会有这个权限。

 

将用户添加到用户组或者给用户组(group)添加权限,一般建议直接通过django admin进行。如果你希望手动给group添加或删除权限,你可以使用如下方法。

mygroup.permissions = [permission_list]mygroup.permissions.add(permission, permission, ...)mygroup.permissions.remove(permission, permission, ...)mygroup.permissions.clear()

如果你要将某个用户移除某个用户组,可以使用如下方法。

myuser.groups.remove(group, group, ...) #myuser.groups.clear()

 

Django自带权限机制的不足

 

Django自带的权限机制是针对模型的,这就意味着一个用户如果对Article模型有change的权限,那么该用户获得对所有文章对象进行修改的权限。如果我们希望实现对单个文章对象的权限管理,我们需要借助于第三方库比如django guardian。至于该库的使用,我们以后再详细介绍。

 

最近身体稍有不适,更新较慢,还请见谅啊。后面小编我会介绍更多Django的技术知识,包括装饰器和信号,欢迎关注。

 

大江狗

 

大江狗

转载地址:http://bstp.baihongyu.com/

你可能感兴趣的文章
nginx配置全解
查看>>
Nginx配置参数中文说明
查看>>
Nginx配置后台网关映射路径
查看>>
nginx配置域名和ip同时访问、开放多端口
查看>>
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置如何一键生成
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>
Nginx配置文件nginx.conf中文详解(总结)
查看>>
Nginx配置负载均衡到后台网关集群
查看>>
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
查看>>
NIFI1.23.2_最新版_性能优化通用_技巧积累_使用NIFI表达式过滤表_随时更新---大数据之Nifi工作笔记0063
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
查看>>