本文目录导读:

- 原生支持:模型级别的细粒度(最常用)
- 社区最佳实践:使用
django-guardian实现对象级别权限 - 字段级别的细粒度控制(原生或第三方)
- 视图/API 级别的细粒度控制(原生 + DRF)
- 新时代的选择:
django-role-permissions或 自制 RBAC - 总结:你应该怎么选?
是的,Django 的权限系统在很多方面已经支持了更细粒度的控制,但具体实现方式取决于你的需求是“框架原生支持”还是“需要第三方库或自定义”。
Django 原生权限系统长期以来只提供了 模型级别(Model Level) 的权限(即:添加、修改、删除、查看某个模型的全部实例),如果你需要对单个数据行(对象级别,Object Level) 或某个字段进行权限控制,原生系统是不够的。
但别担心,Django 社区和框架本身在近几个版本中为“更细粒度”提供了非常强大的支持。
以下是 Django 权限系统实现“更细粒度”控制的几种主流方式和现状:
原生支持:模型级别的细粒度(最常用)
Django 自带了一套完整的权限框架,通过 django.contrib.auth 实现,虽然它默认只提供 add, change, delete, view(Django 2.1+ 引入)四种权限,但你可以轻松自定义。
如何实现:
# 在模型的 Meta 类中定义自定义权限
class Article(models.Model):= models.CharField(max_length=100)
status = models.CharField(max_length=20, choices=[('draft', 'Draft'), ('published', 'Published')])
class Meta:
permissions = [
("publish_article", "Can publish article"), # 自定义权限
("can_edit_draft", "Can edit draft articles"), # 另一个自定义权限
]
- 优点:完全原生,无需第三方库,迁移后自动在
auth_permission表中生成。 - 局限性:权限颗粒度是整个模型的,你不能直接用原生系统控制“用户A只能编辑自己创建的文章”,也不能控制“用户B只能编辑状态为草稿的文章”。
社区最佳实践:使用 django-guardian 实现对象级别权限
这是目前最流行、最成熟的第三方库,专门用来补充 Django 原生的权限系统,实现对象级别(Object Level)的细粒度控制。
- 功能:你可以为每个用户或用户组,针对某个具体的对象实例分配权限。
用户A对文章ID#5有change权限。用户B对文章ID#10有view权限。
- 使用场景:多用户协作的文档系统、CRM系统(每个销售人员只能看自己的客户)、任务管理系统。
from guardian.shortcuts import assign_perm, get_perms
# 赋予用户 alice 对特定文章 article_obj 的更改权限
assign_perm('change_article', alice, article_obj)
# 检查 alice 是否有权限
alice.has_perm('change_article', article_obj) # True/False
- 需要:安装
django-guardian,并在settings.py的AUTHENTICATION_BACKENDS中添加它。
字段级别的细粒度控制(原生或第三方)
如果你想控制某个用户能否看到或编辑模型的某个字段(普通员工不能看到“薪资”字段,HR可以看到),Django 原生没有直接支持,但可以通过以下方式实现:
- 方法1:自定义
ModelForm+ 视图逻辑。- 在
get_form()方法中,根据用户的组或权限动态修改fields或exclude属性。
- 在
- 方法2:使用
django-rules。这是一个轻量级的权限引擎,基于谓词逻辑(predicates),非常适合实现复杂条件(包括字段级别)。
- 方法3:序列化器层(DRF 中有用)。
如果你用 Django REST Framework,可以在序列化器中动态控制字段是否显示。
视图/API 级别的细粒度控制(原生 + DRF)
除了模型,你还可以在视图(View)层面进行细粒度控制。
- Django 原生:
PermissionRequiredMixin可以检查是否拥有某个自定义权限。 - Django REST Framework:提供了强大的权限类(
BasePermission),你可以继承并实现自己的has_permission(请求级别)和has_object_permission(对象级别)方法。
from rest_framework.permissions import BasePermission
class IsOwnerOrReadOnly(BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in ('GET', 'HEAD', 'OPTIONS'):
return True
return obj.owner == request.user
新时代的选择:django-role-permissions 或 自制 RBAC
如果你需要基于角色的复杂权限模型(如:角色可继承、角色有多个粒度),可以考虑:
django-role-permissions:提供了角色、权限组、权限检查等功能。- 自制设计:对于大型项目,很多团队会直接自己设计,利用 Django 的
Group和一个Permission关联表,结合缓存,实现高度定制化的 ACL(访问控制列表)。
你应该怎么选?
| 你的需求粒度 | 推荐方案 | 是否原生 |
|---|---|---|
| 模型级别 (增删改查整个模型表) | Django 内置权限 + 自定义权限 | ✅ 完全原生 |
| 对象级别 (控制对某个具体记录的访问) | django-guardian |
❌ 第三方库 |
| 字段级别 (控制用户能否看到/编辑某列) | 自定义 ModelForm 或 View 逻辑 |
✅ 原生实现 |
| 视图/API级别 (根据用户角色返回不同数据) | Django 原生 PermissionRequiredMixin 或 DRF 权限类 |
✅ 原生/DRF |
| 复杂业务逻辑规则 (如:非工作时间不能操作) | django-rules 或自定义装饰器 |
❌ 第三方库 |
Django 本身的内置权限系统是比较基础的(模型级别),但得益于其强大的插件生态(尤其是 django-guardian 和 django-rules)以及强大的自定义视图/表单能力,Django 完全可以实现非常细粒度的权限控制(对象级、字段级、甚至函数级),是不是“更细粒度”取决于你是否愿意引入这些工具或写好自定义逻辑,对于大多数业务系统来说,内置权限 + django-guardian 基本上能覆盖 90% 的场景。