You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Django权限系统实现特定模型实例的细粒度权限控制

你可以通过Django官方提供的自定义授权后端能力实现该需求,这是最符合Django设计规范的实现方式,比修改Group模型的方案更优雅,同时支持单用户权限分配和组权限分配。

1. 新增项目权限关联模型

新增两个中间表,分别存储用户、用户组与特定项目绑定的权限,完全复用Django原生的Permission模型,不需要修改核心权限逻辑:

from django.db import models
from django.contrib.auth.models import User, Group, Permission

# 你的原有模型
class Project(models.Model):
    pass

class Page(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)

# 新增的权限关联模型
class ProjectUserPermission(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="project_permissions")
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)

    class Meta:
        unique_together = ("user", "project", "permission")

class ProjectGroupPermission(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name="project_permissions")
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)

    class Meta:
        unique_together = ("group", "project", "permission")

2. 实现自定义授权后端

Django的授权后端支持自定义has_perm方法,且原生支持传入被校验的对象参数,完全匹配你的需求:

from django.contrib.auth.backends import BaseBackend

class ProjectPermissionBackend(BaseBackend):
    def has_perm(self, user_obj, perm, obj=None):
        # 超级用户默认拥有所有权限
        if user_obj.is_superuser:
            return True
        # 未传入对象时不做校验(或可按需保留默认全局权限校验逻辑)
        if obj is None:
            return False
        # 自动提取关联的Project实例,支持直接传入Page等子资源对象
        project = obj.project if hasattr(obj, "project") else obj
        # 提取权限codename(perm格式为<app_label>.<codename>)
        perm_codename = perm.split(".")[-1]

        # 校验用户单独分配的项目权限
        if user_obj.project_permissions.filter(
            project=project, 
            permission__codename=perm_codename
        ).exists():
            return True
        
        # 校验用户所属组分配的项目权限
        if ProjectGroupPermission.objects.filter(
            group__in=user_obj.groups.all(),
            project=project,
            permission__codename=perm_codename
        ).exists():
            return True
        
        return False

3. 配置授权后端

在项目settings.py中注册自定义的授权后端,可选择保留默认的全局权限后端:

AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend", # 保留默认全局权限校验,不需要可删除
    "your_app_name.path.to.ProjectPermissionBackend", # 替换为你自定义后端的实际路径
]

4. 使用方式

直接调用Django原生的has_perm方法即可实现你需要的校验能力,不需要额外封装函数:

# 校验用户对project1是否有view_page权限
user.has_perm("your_app_name.view_page", obj=project1)
# 直接传入Page实例也可自动关联到所属项目校验
page = Page.objects.get(id=xxx)
user.has_perm("your_app_name.view_page", obj=page)

如果你不想自行实现底层逻辑,也可以直接使用成熟的第三方对象级权限库django-guardian,它已经封装了完整的按实例分配权限的能力,原生兼容Django的has_perm接口。


内容的提问来源于stack exchange,提问作者Sören Weber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 09:06:03