Django中访问权限的控制
在使用django时,常常有需求关于限定特定的人的查看和操作行为等,比如未登录无法查看内容,比如只有赋予权限的人才能新增记录。对此这样的需求,有几种处理方式。
(如果是用到了django restframework,则可以参考另一篇文章:Django restframework加Vue打造前后端分离的网站(八)权限控制)
django的每一个model对象都有四种操作类型,在admin也能看到:view, add, change, delete,分别对应查看、添加、修改、删除。对于superuser则是默认拥有所有权限,对于普通用户可以单独赋予某种对象的某种操作的权限,也可以创建一个群组group定义好权限列表,并将该用户添加到该群组。
但我们需要指定哪种类型的用户或者哪种类型的权限能做什么事。
该文章分成两个部分:按django权限类型管理,按自定义逻辑判断。
1. 按django权限类型管理
django提供了可供使用的装饰器:login_required,permission_required。此外还有PermissionRequiredMixin可以用。
login_required是指要求必须登录;在参数中如果指定了login_url则会在未登录时跳转该地址。
比如下面的例子,在views.py中定义,如果此时未登录,则无法查看该页面了。
from django.contrib.auth.decorators import login_required
@login_required
def about_site(request):
return render(request, 'blog/about_site.html')
permission_required是指要求拥有某个权限,且可以有多重的permission_required装饰器。在参数中如果指定了login_url则会在未登录时跳转该地址。在参数中如果指定了raise_exception为True时则会抛出403的错误。
需要指定权限类型,格式是app_label和model name,app_label就是在settings里写的app,model name就是自己定义的model加上操作类型。
比如下面的例子,是需要有blog这个app的add_post权限,才被允许使用对应的views函数,才能看到post的详细内容。既然是装饰器,那么多重权限检查也是支持的。
from django.contrib.auth.decorators import permission_required
@permission_required('blog.add_post', raise_exception=True)
# @permission_required('blog.view_post', raise_exception=True)
def post_detail(request, post_id):
post = get_object_or_404(Post, pk=post_id)
return render(request, 'blog/post_detail.html', {'post': post})
如果views里定义的是一个class,那么还可以继承PermissionRequiredMixin来控制,需要指定单个或者多个的permission_required,和上面的装饰器的作用一样。比如官方的这个例子:
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
permission_required = 'polls.add_choice'
# Or multiple of permissions:
permission_required = ('polls.view_choice', 'polls.change_choice')
2. 按自定义逻辑判断
自定义逻辑就是根据根据django内置方法来设置条件,根据条件来决定是否展示或者提供操作。当然这个不如方法1那么合理,但也能产生类似的效果。只是需要注意的是,这里即使无法访问,一般仍会根据条件来走并返回200而不是403,并不规范。但这种方式也不是完全没用途,像遇到自定义字段的区别来展示不同内容时,遇到不同设备来展示不同内容时,这是非常方便的。
自定义的逻辑可以在views中,也可以在template中。
按上述的例子,我们再来做一遍。
判断是否登录,就可以用user.is_authenticated。
在views中可以是这样:
def about_site(request):
if request.user.is_authenticated:
return render(request, 'blog/about_site.html')
else:
return render(request, 'error/unauthenticated.html')
在template中可以是这样:
{% if user.is_authenticated %}
<h3>this is topic</h3>
{% else %}
<h3>Please login first to view this page</h3>
{% endif %}
判断是否有操作权限,可以用has_perm。
在views中可以是这样:
def post_detail(request, post_id):
if request.user.has_perm('blog.add_post'):
post = get_object_or_404(Post, pk=post_id)
return render(request, 'blog/post_detail.html', {'post': post})
else:
return render(request, 'error/unauthenticated.html')
用户所拥有的权限被存储在{{ perms }},views中的request.user.has_perm('blog.add_post') 就等同于 template中的 {% if perms.blog.add_post %}。
于是在template中可以是这样:
{% if perms.blog.view_post %}
<h3>this is topic</h3>
{% else %}
<h3>Please login first to view this page</h3>
{% endif %}
到此就介绍完了django中怎么根据权限来控制展示和行为了。