Django内置权限管理详解:默认权限、自定义权限及模板验证
本文详解Django内置的权限管理机制,涵盖add、change、delete、view四个默认权限的数据库存储结构,以及如何通过Meta类定义自定义权限。同时介绍在视图函数中使用@permission_required装饰器进行权限校验,以及在模板中通过自定义过滤器和全局变量perms实现前端权限控制的具体方法。
Django内置权限管理详解:默认权限、自定义权限及模板验证
前言
部分企业内部的内容管理系统(CMS)需要限制特定内容仅对指定用户可见,此时利用Django内置的权限管理模块进行限制是一种便捷且高效的方案。
需要注意的是,Django内置权限默认基于Model(模型)级别,无法直接针对单条数据记录进行细粒度控制。若需实现单条数据的权限控制,必须通过额外的逻辑或中间件进行处理。
默认权限(add, change, delete, view)
默认权限(add, change, delete, view)
Django为每个定义的Model自动生成四个基础权限:add(新增)、change(修改)、delete(删除)和view(查看)。以名为Log的Model为例,这四个默认权限在数据库中的存储格式如下所示。
数据存储在auth_permission表中(注:id字段值为系统自动生成,执行python manage.py migrate时会自动生成对应记录)。
| id | name | content_type_id | codename |
|---|---|---|---|
| 1 | Can add log | 7 | add_log |
| 2 | Can change log | 7 | change_log |
| 3 | Can delete log | 7 | delete_log |
| 4 | Can view log | 7 | view_log |
字段含义解析
id:由数据库自动生成的唯一标识。
name:权限的描述性文本,主要用于后台展示,实际逻辑校验中作用较小。
content_type_id:关联django_content_type表的id字段,用于标识该权限所属的应用和模型。
codename:权限的代码标识,例如通过add_log表示用户对Log模型拥有新增权限。系统在进行权限验证时,主要依据此字段的值进行匹配。
若模型名称变更为Student,只需将上述表中的log替换为student即可,结构保持一致。
name字段中的“Can add xx”、“Can change xx”等为固定格式,其中xx部分随模型名称动态变化。
同理,codename字段也遵循固定格式,如add_xxx、change_xxx,xxx部分对应模型名。
auth_permission表中的content_type_id字段尚未解释,接下来查看django_content_type表以明确其对应关系。
数据存储在django_content_type表中。
| id | app_label | model |
|---|---|---|
| 1 | admin | logentry |
| 3 | auth | group |
| 2 | auth | permission |
| 4 | auth | user |
| 5 | contenttypes | contenttype |
| 6 | sessions | session |
| 7 | test | log |
字段含义解析
id:自增主键,auth_permission表中的content_type_id字段即指向此值。
app_label:标识该模型所属的应用包名称,例如前文提到的Log模型属于test应用。
model:模型的具体名称。
使用方法
使用方法
在视图函数中验证权限,可使用user.has_perm方法。
举例说明:假设有一个书店系统,包含普通员工User模型和书籍Book模型。当需要判断员工A是否有权利向出版社订购书籍(即执行add_book操作)时,可通过以下代码验证。
user = User.objects.get(username='A')
# has_permission是一个boolean,因为Book模型是放在test app下面的
has_permission = user.has_perm('test.add_book')
为何在验证权限字符串前需加上app名?这是为了区分不同应用中可能存在的同名权限,确保权限校验的准确性。
若需验证视图函数是否具有执行权限,可使用@permission_required装饰器。
@permission_required
def function():
pass
permission_required装饰器接受三个参数:
perm:描述权限的字符串,格式为“应用名.权限标识”,例如“auth.add_user”或“auth.delete_user”。
login_url:当用户无权限时跳转的URL地址,例如“/login”或“https://www.baidu.com”。
raise_exception:布尔值,指定无权限时是否触发PermissionDenied异常。若设为True,则直接抛出异常并返回,不会跳转至login_url指定的地址。
在Template模板中使用权限验证
在Template模板中使用权限验证
第一种实现方式
首先,需在应用根目录下创建一个名为templatetags的包(IDE通常会自动生成__init__.py文件),并在该包内创建my_tags.py文件。在my_tags.py中定义一个名为has_permisstion的过滤器,用于对用户权限进行验证,该过滤器接收两个参数:
user:当前登录的用户对象。
perm:需要验证的权限字符串。
from django import template
register = template.Library()
@register.filter
def has_permisstion(user, perm):
if user:
return user.has_perm(perm)
return False
随后,创建一个名为index.html的模板页面,务必在页面顶部加载自定义标签文件{% load my_tags %}。
<!DOCTYPE html>
{% load my_tags %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p>后面的内容只有有权限的人才能看到,
{% if request.user|has_permisstion:'test.add_department' %}
我有权限
{% endif %}
</p>
</body>
</html>
目录结构如下所示。

演示结果:假设用户已登录且拥有相应权限,页面将显示对应内容。

第二种实现方式
利用模板中的全局变量perms进行验证,例如使用perms.test.add_department。
{% if perms.应用名.权限标识 %}
<!-- 这里是有权限才显示的内容 -->
{% endif %}
自定义权限
自定义权限
首先,在test应用的model文件中创建Department模型,并为其添加自定义权限。
class Department(models.Model):
name = models.CharField(null=True, max_length=20)
user = models.ManyToManyField(User)
one_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='one_user')
class Meta:
# permissions是一个元组,记得每组权限后面加逗号,下面是一组权限
permissions = (
# (权限,权限描述),
('customize_permission', 'This is my customize permission'),
)
执行以下命令以同步数据库修改:
python manage.py makemigrations python manage.py migrate
系统输出显示增加成功。
>> Migrations for 'test':
test\migrations\0003_auto_20200407_1645.py
- Change Meta options on department
打开数据库验证,确认权限已成功添加。

此后,即可像使用默认权限一样,通过customize_permission这一自定义权限进行控制。
以上关于Django内置权限管理Permission的用法说明即为全部内容,希望能为大家提供参考,并欢迎大家支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













