Django实现:如何为不同社团启用应用使用权限
解决方案
1. 扩展社团模型,添加应用权限关联
首先在core/models.py中给SocietyEntity添加关联字段,用来记录该社团有权限访问的应用。推荐创建一个独立的App模型来统一管理项目中的应用,这样后台操作更直观、规范:
from django.contrib.auth import get_user_model from django.db import models class App(models.Model): name = models.CharField(max_length=50, unique=True, verbose_name="应用标识") display_name = models.CharField(max_length=100, verbose_name="应用名称") def __str__(self): return self.display_name class SocietyEntity(models.Model): id = models.AutoField(primary_key=True) referenceName = models.CharField(max_length=200, verbose_name="Nombre") members = models.ManyToManyField(get_user_model(), related_name="joined_societies") administrator = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, verbose_name="Administrator", related_name="managed_societies") # 新增多对多字段,关联允许访问的应用 allowed_apps = models.ManyToManyField(App, blank=True, verbose_name="允许访问的应用")
完成后执行数据库迁移:
python manage.py makemigrations python manage.py migrate
如果不想新增App模型,也可以直接用字符串选项存储应用名称(适合小型项目):
# 定义项目内的应用选项 APP_CHOICES = [ ('blog', '博客应用'), ('events', '活动管理'), # 补充你的其他应用 ] class SocietyEntity(models.Model): # 原有字段... allowed_apps = models.ManyToManyField( 'self', through=None, blank=True, verbose_name="允许访问的应用", choices=APP_CHOICES, to_field="referenceName" )
2. 定制Admin站点,过滤可见应用
重写Django Admin的站点逻辑,根据当前登录用户所属/管理的社团权限,过滤后台显示的应用:
# core/admin.py from django.contrib.admin import AdminSite from django.contrib import admin from django.apps import apps class CustomAdminSite(AdminSite): def get_app_list(self, request, app_label=None): app_list = super().get_app_list(request, app_label) current_user = request.user # 超级用户默认显示所有应用 if current_user.is_superuser: return app_list # 获取用户有权限的应用标识列表 allowed_app_names = [] # 优先获取用户管理的社团权限 managed_societies = current_user.managed_societies.all() if managed_societies.exists(): allowed_app_names = list(managed_societies.values_list('allowed_apps__name', flat=True).distinct()) else: # 若无管理权限,获取用户加入的社团权限 joined_societies = current_user.joined_societies.all() if joined_societies.exists(): allowed_app_names = list(joined_societies.values_list('allowed_apps__name', flat=True).distinct()) else: # 无任何社团权限,仅显示core应用 return [app for app in app_list if app['app_label'] == 'core'] # 过滤应用列表,保留允许的应用和core核心应用 filtered_apps = [] for app in app_list: if app['app_label'] in allowed_app_names or app['app_label'] == 'core': filtered_apps.append(app) return filtered_apps # 实例化自定义Admin站点 custom_admin_site = CustomAdminSite(name='custom_admin') # 自动注册所有模型到自定义站点(也可手动注册指定模型) for model in apps.get_models(): try: custom_admin_site.register(model) except admin.sites.AlreadyRegistered: pass
最后修改项目的urls.py,替换默认的Admin路径:
# project/urls.py from django.contrib import admin from core.admin import custom_admin_site urlpatterns = [ # 注释默认Admin路由 # path('admin/', admin.site.urls), path('admin/', custom_admin_site.urls), # 其他路由... ]
3. 注意事项
- 如果使用字符串选项的方式存储应用权限,需要在
get_app_list中调整allowed_app_names的提取逻辑,直接读取字段值即可。 - 若有自定义的
ModelAdmin类,需确保注册到自定义的custom_admin_site上,可通过custom_admin_site.register(Model, ModelAdmin)指定。
内容的提问来源于stack exchange,提问作者GonzaloN
相关产品推荐
相关产品推荐

