Django权限机制实现代码详解

本文研究的主要是Django权限机制的相关内容,具体如下。

1. Django权限机制概述

权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活;用好权限机制,能让系统更加强大和健壮。因此,基于Django的开发,理清Django权限机制是非常必要的。

1.1 Django的权限控制

Django用user, group和permission完成了权限机制,这个权限机制是将属于model的某个permission赋予user或group,可以理解为全局的权限,即如果用户A对数据模型(model)B有可写权限,那么A能修改model B的所有实例(objects)。group的权限也是如此,如果为group C 赋予model B的可写权限,则隶属于group C 的所有用户,都可以修改model B的所有实例。

这种权限机制只能解决一些简单的应用需求,而大部分应用场景下,需要更细分的权限机制。以博客系统为例,博客系统的用户可分为『管理员』、『编辑』、『作者』和『读者』四个用户组;博客系统管理员和编辑具有查看、修改和删除所有的文章的权限,作者只能修改和删除自己写的文章,而读者则只有阅读权限。管理员、编辑和读者的权限,我们可以用全局权限做控制,而对于作者,全局权限无法满足需求,仅通过全局权限,要么允许作者编辑不属于自己的文章,要么让作者连自己的文章都无法修改。

上述的应用场景,Django自带的权限机制无法满足需求,需要引入另一种更细的权限机制:对象权限(object permission)。

Object Permission是一种对象颗粒度上的权限机制,它允许为每个具体对象授权。仍沿用最开始的例子,如果model B有三个实例 B1,B2 和B3,如果我们把B1的可写权限赋予用户A,则A可以修改B1对象,而对B2,B3无法修改。

对group也一样,如果将B2的可写权限赋予group C,则隶属于group C的所有用户均可以修改B2,但无法修改B1和B3。结合Django自带权限机制和object permission,博客系统中作者的权限控制迎刃而解:系统全局上不允许作者编辑文章,而对于属于作者的具体文章,赋予编辑权限即可。

Django其实包含了object permission的框架,但没有具体实现,object permission的实现需要借助第三方app django-guardian,我们在开发中用调用django guradian封装好的方法即可。

1.2 Django的权限项

Django用permission对象存储权限项,每个model默认都有三个permission,即add model, change model和delete model。例如,定义一个名为『Car』model,定义好Car之后,会自动创建相应的三个permission:add_car, change_car和delete_car。Django还允许自定义permission,例如,我们可以为Car创建新的权限项:drive_car, clean_car, fix_car等等

需要注意的是,permission总是与model对应的,如果一个object不是model的实例,我们无法为它创建/分配权限。

2. Django 自带权限机制的应用

2.1 Permission

如上文所述,Django定义每个model后,默认都会添加该model的add, change和delete三个permission,自定义的permission可以在我们定义model时手动添加:

class Task(models.Model):
  ...
  class Meta:
    permissions = (
      ("view_task", "Can see available tasks"),
      ("change_task_status", "Can change the status of tasks"),
      ("close_task", "Can remove a task by setting its status as closed"),
    )

每个permission都是django.contrib.auth.Permission类型的实例,该类型包含三个字段name, codename 和 content_type,其中 content_type反应了permission属于哪个model,codename如上面的view_task,代码逻辑中检查权限时要用, name是permission的描述,将permission打印到屏幕或页面时默认显示的就是name。

在model中创建自定义权限,从系统开发的角度,可理解为创建系统的内置权限,如果需求中涉及到用户使用系统时创建自定义权限,则要通过下面方法:

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(codename='can_publish',
                    name='Can Publish Posts',
                    content_type=content_type)

2.2 User Permission管理

User对象的user_permission字段管理用户的权限:

myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...) #增加权限
myuser.user_permissions.remove(permission, permission, ...) #删除权限
myuser.user_permissions.clear() #清空权限

##############################################################
# 注:上面的permission为django.contrib.auth.Permission类型的实例
##############################################################

检查用户权限用has_perm()方法:

myuser.has_perm('myapp.fix_car')

has_perm()方法的参数,即permission的codename,但传递参数时需要加上model 所属app的前缀,格式为<app label>.<permission codename>

无论permission赋予user还是group,has_perm()方法均适用

附注:
user.get_all_permissions()方法列出用户的所有权限,返回值是permission name的list
user.get_group_permissions()方法列出用户所属group的权限,返回值是permission name的list

2.3 Group Permission管理

group permission管理逻辑与user permission管理一致,group中使用permissions字段做权限管理:

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

权限检查:

依然使用user.has_perm()方法。

2.4 permission_required 装饰器

权限能约束用户行为,当业务逻辑中涉及到权限检查时,decorator能够分离权限验证和核心的业务逻辑,使代码更简洁,逻辑更清晰。permission的decorator为permission_required

from django.contrib.auth.decorators import permission_required

@permission_required('car.drive_car')
def my_view(request):

2.5 Template中的权限检查

Template中使用全局变量perms存储当前用户的所有权限,权限检查可以参考下面例子:

{% if perms.main.add_page %}
      <li class="dropdown">
       <a href="#" rel="external nofollow" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Pages <span class="caret"></span></a>
       <ul class="dropdown-menu" role="menu">
        <li><a href="{% url 'main:admin_pages' %}" rel="external nofollow" >All Pages</a></li>
        <li><a href="{% url 'main:admin_page' %}" rel="external nofollow" >New Page</a></li>
        <li><a href="{% url 'main:admin_pages' %}?draft=true" rel="external nofollow" >Drafts</a></li>
       </ul>
      </li>
{% endif %}

3. 基于Django-guardian的object permission的应用

Django-guardian基于django的原生逻辑扩展了django的权限机制,应用django-guardian后,可以使用django-guardian提供的方法以及django的原生方法检查全局权限,django-guardian提供的object permission机制使django的权限机制更加完善。

django-guardian详细的使用文档请参考官方文档,其object permission常用方法如下:

from guardian.shortcuts import assign_perm, get_perms
from guardian.core import ObjectPermissionChecker
from guardian.decorators import permission_required

3.1 添加object permission

添加object permission使用assign_perm()方法,如为用户添加对mycar对象的drive_car权限:

assign_perm('myapp.drive_car', request.user, mycar)

assign_perm()方法也可用于group

assign_perm('myapp.drive_car', mygroup, mycar)

3.2 权限检查

3.2.1 Global permission

get_perms()方法用于检查用户的“全局权限”(global permission),与user.has_perm()异曲同工,如:

#############################
# It works!
#############################
 if not 'main.change_post' in get_perms(request.user, post):
   raise HttpResponse('Forbidden')

#############################
# It works, too!
#############################
if not request.user.has_perm('main.change_post')
  return HttpResponse('Forbidden')

例子中虽然把post object作为参数传给get_perms()方法,但它只检查user的全局权限中是否有main.change_post权限,很多情况下可用原生的user.has_perm取代,但user和group均可作为get_perms()的传入参数,某些情况下可以使代码更简洁。

3.2.2 Object permission

Django-guardian中使用ObjectPermissionChecker检查用户的object permission,示例如下:

checker = ObjectPermissionChecker(request.user)
print checker.has_perm('main.change_post', post)

3.3 permission_required装饰器

guardian.decorators.permission_required是django-guardian权限检查的decorator,既可以检查全局权限,又可以检查对象权限(object permission),其中,accept_global_perms参数指出是否检查user的global permission,如:

from guardian.decorators import permission_required

class DeletePost(View):
  @method_decorator(permission_required('main.delete_post',
              (models.Post, 'id', 'pk'),
              accept_global_perms=True))
  def get(self, request, pk):
    try:
      pk = int(pk)
      cur_post = models.Post.objects.get(pk=pk)
      is_draft = cur_post.is_draft

      url = reverse('main:admin_posts')
      if is_draft:
        url = '{0}?draft=true'.format(url)
      cur_post.delete()
    except models.Post.DoesNotExist:
      raise Http404

    return redirect(url)

注:
decorator中的(models.Post, ‘id', ‘pk')部分,用于指定object实例,如果忽略这个参数,则不论accept_global_perms值为True还是False,均仅仅检查全局权限。

4. 结论

Django原生提供了一种简单的全局权限(global permission)控制机制,但很多应用场景下,对象权限(object permission)更加有用;django-guardian是目前比较活跃的一个django extension,提供了一种有效的object permission控制机制,与django原生机制一脉相承,推荐使用。

以上就是本文关于Django权限机制实现代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

您可能感兴趣的文章:

  • 使用python和Django完成博客数据库的迁移方法
  • python+django加载静态网页模板解析
  • Python通过Django实现用户注册和邮箱验证功能代码
  • Python中django学习心得
  • Python使用django框架实现多人在线匿名聊天的小程序
  • Python之Django环境搭建教程(MAC+pycharm+Django++postgreSQL)
  • 如何在sae中设置django,让sae的工作环境跟本地python环境一致
  • 在python3环境下的Django中使用MySQL数据库的实例
(0)

相关推荐

  • 如何在sae中设置django,让sae的工作环境跟本地python环境一致

    sae中安装有python环境,想让sae导入自己下载的django或者其他模块,可以在svn中新建一个文件目录,比如site-packages,跟python安装目录一样,这个目录存放所有的python模块(包括django),将安装目录下的以及用pip install安装的各种模块copy入这个目录,然后增加python搜索路径,让sae可以从这个目录引入各种模块,保证程序正常运行.具体设置如下: 第一步:修改wsgi.py文件,该文件在django生成的项目目录后,比如../mysite/

  • Python中django学习心得

    以下是作者在学习Python中django框架时的学习笔记,并把测试的代码做了详细分析,最后还附上了学习心得,值得大家学习. URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码. '''urlpatterns = [url(正则表达式, views视图函数,参数,别名),]参数说明:一个正则表达式字符串一个可调用对象,通常为一个视图函数或

  • Python使用django框架实现多人在线匿名聊天的小程序

    最近看到好多设计类网站,都提供了多人在线匿名聊天的小功能,感觉很有意思,于是基于python的django框架自己写了一个,支持手动实时更名,最下方提供了完整的源码. 在线聊天地址(无需登录,开一个窗口,代表一个用户): http://zhaozhaoli.vicp.io/chatroom/happy/ 移动端聊天效果图: 网页版聊天效果图: 实现思路: 发送的消息通过ajax先写入数据库,通过ajax的循环请求,将写入数据库的消息显示到前端界面. 前端核心代码: <script> $(fun

  • 在python3环境下的Django中使用MySQL数据库的实例

    我们在使用Django过程中,数据库往往是离不开的,比较长常用的是MySQL数据库,但在使用过程中,对Python不同的版本对用的库也不一样,用惯了Python2的人在使用Python3时经常会遇到下面的错误: Error loading MySQLdb module: No module named 'MySQLdb'. 这是因为Python3 MySQL的支持库为pymysql所致,所以我们要下载pymysql数据库. 并且在站点文件夹下的__init__.py(project同名目录下,而

  • python+django加载静态网页模板解析

    接着前面Django入门使用示例 今天我们来看看Django是如何加载静态html的? 我们首先来看一看什么是静态HTML,什么是动态的HTML?二者有什么区别? 静态HTML指的是使用单纯的HTML或者结合CSS制作的包括图片.文字等的只供用户浏览但不包含任何脚本.不含有任何交互功能的网页! 动态的HTML指的是网页不仅提供给用户浏览,网页本身还有交互功能,存在着在脚本如JAVASCRIPT,并利用某种服务器端语言如PHP等实现如用户注册,用户登录,上传文件,下载文件等功能 接下来,了解下加载

  • 使用python和Django完成博客数据库的迁移方法

    上一讲完成了基本博客的配置和项目工程的生成.这次开始将博客一些基本的操作主要是数据库方面学习. 1.设计博客数据库表结构 博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个地方就是数据库.我们把写好的文章永久地保存在数据库里,当用户访问我们的博客时,Django 就去数据库里把这些数据取出来展现给用户. 博客的文章应该含有标题.正文.作者.发表时间等数据.一个更加现代化的博客文章还希望它有分类.标签.评论等.为了更好地存储这些数据,我们需要合理

  • Python之Django环境搭建教程(MAC+pycharm+Django++postgreSQL)

    搭建Django环境似乎是一件很简单的事情,其实不然,苦命的我折腾了大半天才好, 遂在此总结下整个搭建过程,同时也愿刚入门的同行少走弯路~ 现在开始,所需工具: MAC电脑 Pycharm 2017 for MAC jdk1.8 Python3.6 postgreSQL 9.6.6 Toad/navicat/pgAdmin 数据库工具 (非必须) 大致需要这些东西,至于为什么要装jdk,大概是Pycharm本身部分依赖于java环境,可以看看产品说明可略窥一二: 嗯~,还有postgreSQL如

  • Python通过Django实现用户注册和邮箱验证功能代码

    本文主要向大家分享了Python编程中通过Django模块实现用户注册以及邮箱验证功能的简单介绍及代码实现,具体如下. 用户注册: 类似于用户登陆,同样在users.views.py中添加RegisterView(View)类,其中对表单的get和post作出处理. 如果是get方法,重新返回register页面让用户进行填写. def get(self, request): register_form = RegisterForm() return render(request, "regis

  • Django权限机制实现代码详解

    本文研究的主要是Django权限机制的相关内容,具体如下. 1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发,理清Django权限机制是非常必要的. 1.1 Django的权限控制 Django用user, group和permission完成了权限机制,这个权限机制是将属于model的某个permission赋予user或group,可以理解为全局的权限,即如果用户A对数

  • Django中的Signal代码详解

    本文研究的主要是Django开发中的signal 的相关内容,具体如下. 前言 在web开发中, 你可能会遇到下面这种场景: 在用户完成某个操作后, 自动去执行一些后续的操作. 譬如用户完成修改密码后, 你要发送一份确认邮件. 当然可以把逻辑写在一起,但是有个问题是,触发操作一般不止一种(如用户更改了其它信息的确认邮件),这时候这个逻辑会需要写多次,所以你可能会想着DRY(Don't repeat yourself),于是你把它写到了一个函数中,每次调用.当然这是没问题的. 但是, 如果你换个思

  • Java编程访问权限的控制代码详解

    本文研究的主要是Java编程访问权限的控制的相关内容,具体介绍如下. 之前没去注意的修饰符,一般变量前面没添加,一个是不知道有什么用,一个是懒,后面遇到项目的时候就会发现私有和公有区别还是很大的. (1)首先是包名 使用一个类的时候,例如集合类,就需要引入这个包,然后再使用该包下面的类.如: package com.myown.iaiti; public class Print { static void print(String s){ System.out.println(s); } } 自

  • Android权限管理之Permission权限机制及使用详解

    前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过程中讨论比较多的一个知识点Android 6.0 权限适配问题来进行学习,不过我不想直接进入这个主题,所以选择先去了解一下Android的Permission权限机制及使用 Android权限机制: 权限是一种安全机制.Android权限主要用于限制应用程序内部某些具有限制性特性的功能使用以及应用程序之间的组

  • Java编程复用类代码详解

    本文研究的主要是Java编程中的复用类,那么到底复用类是什么东西,又有什么用法,下面具体介绍. 看了老罗罗升阳的专访,情不自禁地佩服,很年轻,我之前以为和罗永浩一个级别的年龄,也是见过的不是初高中编程的一位大牛之一,专访之后,发现老罗也是一步一个脚印的人.别说什么难做,做不了,你根本就没去尝试,也没有去坚持. If you can't fly then run,if you can't run then walk, if you can't walk then crawl,but whateve

  • Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解

    前言 前面的例子都是多个线程在做相同的操作,比如4个线程都对共享数据做tickets–操作.大多情况下,程序中需要不同的线程做不同的事,比如一个线程对共享变量做tickets++操作,另一个线程对共享变量做tickets–操作,这就是大名鼎鼎的生产者和消费者模式. 正文 一,生产者-消费者模式也是多线程 生产者和消费者模式也是多线程的范例.所以其编程需要遵循多线程的规矩. 首先,既然是多线程,就必然要使用同步.上回说到,synchronized关键字在修饰函数的时候,使用的是"this"

  • 通过反射实现Java下的委托机制代码详解

    简述 一直对Java没有现成的委托机制耿耿于怀,所幸最近有点时间,用反射写了一个简单的委托模块,以供参考. 模块API public Class Delegater()//空参构造,该类管理委托实例并实现委托方法 //添加一个静态方法委托,返回整型值ID代表该方法与参数构成的实例.若失败,则返回-1. public synchronized int addFunctionDelegate(Class<?> srcClass,String methodName,Object... params)

  • Django模板继承 extend标签实例代码详解

    在 views.py 上修改 ... def ordered(req): return render(req, "ordered.html") def shopping_car(req): return render(req, "shopping_car.html") 在 urls.py 上修改 ... path('ordered/', views.ordered), path('shopping_car/', views.shopping_car), ... 在

  • django在保存图像的同时压缩图像示例代码详解

    假设我们有一个非常简单的Post模型,它将是一个图像及其描述, from django.db import models class Post(models.Model): text = models.TextField() image = models.ImageField(upload_to='images/') 但是我们要优化图像大小,这将由我们Post的image字段指出. 这样做有充分的理由-它有助于更快地加载网站/应用程序并减少我们的服务器存储. 在使用Django之前,首先让我们简

  • Pytorch图像处理注意力机制解析及代码详解

    什么是注意力机制 注意力机制是一个非常有效的trick,注意力机制的实现方式有许多,我们一起来学习一下 注意力机制是深度学习常用的一个小技巧,它有多种多样的实现形式,尽管实现方式多样,但是每一种注意力机制的实现的核心都是类似的,就是注意力. 注意力机制的核心重点就是让网络关注到它更需要关注的地方. 当我们使用卷积神经网络去处理图片的时候,我们会更希望卷积神经网络去注意应该注意的地方,而不是什么都关注,我们不可能手动去调节需要注意的地方,这个时候,如何让卷积神经网络去自适应的注意重要的物体变得极为

随机推荐