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

如何在Django Admin中实现向特定用户组添加条目及字段级权限控制

Django 细粒度权限控制实现方案

前置说明

你对接LDAP后,只要使用django-auth-ldap等常规插件,会自动将LDAP预定义的组同步到Django原生的auth.Group表中,用户的组隶属关系也会同步更新,不需要额外做组映射,直接调用request.user.groups即可获取用户所属的所有LDAP组。


1. 实现行级权限(组专属/多组共享条目控制)

第一步:改造模型增加权限关联字段

给需要控制访问范围的模型增加多对多字段,存储可访问本条数据的用户组:

from django.db import models
from django.contrib.auth.models import Group

# 以你的Person模型为例
class Person(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=200)
    # 新增权限控制字段,支持关联多个组实现多组共享
    allowed_groups = models.ManyToManyField(Group, related_name="accessible_records")
    # 其他原有字段保持不变

执行makemigrations和migrate同步表结构。后续创建条目时,给allowed_groups添加对应组,即可实现专属条目仅对应组成员可见,添加多个组即可实现跨组共享。

第二步:视图层过滤查询结果

在视图中过滤只返回当前用户有权限访问的条目即可:

函数视图(FBV)示例

from django.contrib.auth.decorators import login_required

@login_required
def persons_view(request):
    # 获取当前用户所属的所有组
    user_groups = request.user.groups.all()
    # 过滤有权限的条目,distinct避免多组共享的条目重复返回
    person_list = Person.objects.filter(allowed_groups__in=user_groups).distinct()
    # 后续原有视图逻辑不变

类视图(CBV)示例

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView

class PersonListView(LoginRequiredMixin, ListView):
    model = Person

    def get_queryset(self):
        user_groups = self.request.user.groups.all()
        return super().get_queryset().filter(allowed_groups__in=user_groups).distinct()

2. 实现字段级权限控制

根据你的技术栈选择对应的实现方式即可:

场景1:前后端分离(DRF接口)

在序列化器中根据用户组过滤返回字段:

from rest_framework import serializers
from .models import Person

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = ["id", "name", "address"]

    def to_representation(self, instance):
        data = super().to_representation(instance)
        current_user = self.context["request"].user
        # 组名和LDAP同步的组名保持一致即可
        if not current_user.groups.filter(name="人事管理组").exists():
            # 无权限则移除敏感字段
            data.pop("address")
        return data

场景2:服务端渲染(模板页面)

先自定义模板过滤器判断用户组权限:

# 应用目录下新建 templatetags/perm_filters.py
from django import template
register = template.Library()

@register.filter(name="has_group")
def has_group(user, group_name):
    return user.groups.filter(name=group_name).exists()

模板中按需渲染字段:

{% load perm_filters %}
{% for person in person_list %}
    <p>姓名:{{ person.name }}</p>
    {% if request.user|has_group:"人事管理组" %}
        <p>地址:{{ person.address }}</p>
    {% endif %}
{% endfor %}

场景3:Admin后台字段控制

如果需要在Admin后台也实现字段权限控制,重写Admin类的对应方法即可:

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    # 控制可见字段
    def get_fields(self, request, obj=None):
        fields = super().get_fields(request, obj)
        if not request.user.is_superuser and not request.user.groups.filter(name="人事管理组").exists():
            fields.remove("address")
        return fields
    
    # 控制Admin列表可见条目,和前端视图保持一致
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        user_groups = request.user.groups.all()
        return qs.filter(allowed_groups__in=user_groups).distinct()

内容的提问来源于stack exchange,提问作者piah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:06:03