Django Admin 根据 Choice 字段动态显示页面及 RBAC 权限管理实现
本文介绍如何在 Django Admin 中根据 Choice 字段值动态显示不同表单区域,并通过 JavaScript 实现交互。同时深入讲解基于 RBAC 模型的权限管理组件开发,包括用户、角色、权限及菜单表的模型设计,利用中间件进行请求权限校验,以及通过自定义模板标签动态生成侧边菜单的完整流程。
以下直接展示核心代码实现,省略冗长背景说明。
Django Admin 动态表单展示实现
一、具体应用场景示例
前端 JavaScript 交互逻辑
tip/tip.js
var react = function () {
if (django.jQuery('#id_tiptype').val() == 'content') {
django.jQuery('#id_content').parent().parent().show(500);
django.jQuery('#id_image').parent().parent().hide(500);
django.jQuery('#id_cropping').parent().parent().hide(500);
}
else {
django.jQuery('#id_content').parent().parent().hide(500);
django.jQuery('#id_image').parent().parent().show(500);
django.jQuery('#id_cropping').parent().parent().show(500);
}
};
#当选择的类型改变的时候触发react函数
django.jQuery(function () {
react();
django.jQuery('#id_tiptype').on('change', react);
});
二、Admin 配置代码 (admin.py)
后端 Admin 配置
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from image_cropping import ImageCroppingMixin
from salmonella.admin import SalmonellaMixin
from tip.models import Tip,TipTag
@admin.register(Tip)
class TipAdmin(ImageCroppingMixin, SalmonellaMixin, admin.ModelAdmin):
# search_fields = ('tiptype',)
list_filter = ('enabled',)
list_display = ('tiptype', 'enabled', 'get_tag','image')
salmonella_fields = ('tags', )
# fields = ('tiptype', 'enabled','tags','image')
def get_tag(self, obj):
print(obj.tags.all())
if obj.tags.all():
tag_list = [i.name for i in obj.tags.all()]
return ','.join(tag_list)
else:
return ''
get_tag.short_description = '小贴士标签'
class Media():
js = ('tip/tip.js',)
@admin.register(TipTag)
class TiptagAdmin(admin.ModelAdmin):
search_fields = ('name', )
list_display = ("name", )
基于 RBAC 的权限管理体系
补充知识:Django 中自定义用户权限体系(基于 RBAC 组件)
RBAC 组件概述
RBAC 组件主要用于权限校验,协助管理用户认证信息。不同权限的用户登录后台后,看到的界面展示内容会有所区别。
权限定义:本质上是一个包含正则表达式的 URL 规则。
基于 RBAC 模型设计的数据库表关系如下:

权限模型表结构设计
class User(models.Model):
class Meta:
# 此处设置 admin 中显示名称
verbose_name = verbose_name_plural = '用户表'
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField(to='Role')
def __str__(self):
return self.name
class Role(models.Model):
class Meta:
verbose_name = verbose_name_plural = '职位表'
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(to='Permission')
def __str__(self):
return self.title
class Permission(models.Model):
class Meta:
verbose_name = verbose_name_plural = '权限表'
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
menu=models.ForeignKey("Menu",on_delete=models.CASCADE,null=True)
def __str__(self):
return self.title
class Menu(models.Model):
class Meta:
verbose_name = verbose_name_plural = '菜单表'
title = models.CharField(max_length=32, verbose_name='菜单')
icon = models.CharField(max_length=32, verbose_name='图标', null=True, blank=True)
添加具体的权限信息记录。
通过中间件和自定义模块,实现当前用户权限信息的传输与获取。
权限校验中间件
# 通过自定义 middleware 模块在 setting 中加入,引入中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
import re
class PermissionMiddleWare(MiddlewareMixin):
def process_request(self, request):
current_path = request.path
# 设置白名单
for reg in ['/login/', '/admin/*']:
ret = re.search(reg, current_path)
if ret:
return None
# 校验是否登录
user_id = request.session.get('user_id')
if not user_id:
return redirect('/login/')
# 校验权限
permission_list = request.session.get("permission_list")
for reg in permission_list:
reg = "^%s$" % reg
ret = re.search(reg, current_path)
if ret:
return None
return HttpResponse("无权访问!")
RBAC 自定义模块实现细节
Session 权限初始化
from app1.models import *
def initial_sesson(user, request):
"""
功能:将当前登录人的所有权限录入 session 中
:param user:当前登录人
:param request:
:return:
"""
# 查询当前登录人的所有权限列表
permissions = Role.objects.filter(user=user).values('permissions__url')
print('roles', permissions)
permissions_list = []
for item in permissions:
permissions_list.append(item['permissions__url'])
# 将当前登录人的权限列表注入 session 中
request.session['permission_list'] = permissions_list

动态显示菜单权限逻辑
动态获取并显示菜单,此处特指后台操作界面的展示。
需要获取当前用户的权限信息,包括 URL 路径、是否属于菜单项以及关联的图标。由于涉及数据传递,因此需要定义自定义模板过滤器。
首先定义自定义过滤器逻辑。
动态菜单生成逻辑
# web.py 文件中
from django.utils.safestring import mark_safe
from django.template import Library
import re
register =Library()
@register.inclusion_tag("rbac/menu.html")
# 将当前函数的 permission_menu_dict 传给 rbac 的 menu.html
def get_menu_styles(request):
"""
自定义过滤器
:param request:传入当前用户菜单信息
:return:
"""
permission_menu_dict = request.session.get("permission_menu_dict")
print("permission_menu_dict",permission_menu_dict)
return {"permission_menu_dict":permission_menu_dict}
在 menu.html 模板中使用该过滤器。
菜单模板渲染
# menu.html
<div class="multi-menu">
{% for item in permission_menu_dict.values %}
<div class="item">
<div class="title"><i class="{{ item.menu_icon }}"></i>{{ item.menu_title }}</div>
<div class="body">
{% for foo in item.children %}
<a href="{{ foo.url }}" rel="external nofollow" >{{ foo.title }}</a>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
使用自定义组件进行渲染。
<div class="left-menu">
<div class="menu-body">
{% load web %}
{% get_menu_styles request %}
</div>
</div>
整体界面效果展示。

以上关于 Django Admin 根据 Choice 字段选择不同显示页面及 RBAC 权限管理的实现方式即为全部内容,供参考。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









