效果图:
三级菜单的实现和一级、二级菜单差不多。需要注意的是增加三级菜单时,三级菜单是用户提交后在后台通过二级菜单的id添加的。
一、路由分发
rbac/urls.py
...from django.urls import re_pathfrom rbac.views import menu...urlpatterns = [ ... # 三级菜单 re_path(r'^permission/add/(?P\d+)/$', menu.permission_add, name='permission_add'), re_path(r'^permission/edit/(?P \d+)/$', menu.permission_edit, name='permission_edit'), re_path(r'^permission/del/(?P \d+)/$', menu.permission_del, name='permission_del'), ...]
二、forms表单验证
rbac/forms/base.py
from django import formsclass BaseBootStrapForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs['class'] = 'form-control'
rbac/forms/menus.py
...from rbac import modelsfrom rbac.forms.base import BaseBootStrapForm......class PermissionModelForm(BaseBootStrapForm): class Meta: model = models.Permission fields = ['title', 'name', 'url']...
三、视图函数
rbac/views/menu.py
from django.shortcuts import HttpResponse, render, redirect, reversefrom rbac import modelsfrom rbac.forms.menu import MenuModelForm, SecondMenuModelForm, PermissionModelFormfrom rbac.service.urls import memory_reversedef menu_list(request): """ 菜单和权限列表 :param request: :return: """ menu_queryset = models.Menu.objects.all() menu_id = request.GET.get('mid') # 用户选择的一级菜单 menus_exists = models.Menu.objects.filter(id=menu_id).exists() if not menus_exists: menu_id = None if menu_id: second_menus = models.Permission.objects.filter(menu_id=menu_id) else: second_menus = [] second_menu_id = request.GET.get('sid') # 用户选择的二级菜单 # + second_menus_exists = models.Permission.objects.filter(id=second_menu_id).exists() # + if not second_menus_exists: # + second_menu_id = None # + if second_menu_id: # + permissions = models.Permission.objects.filter(pid__id=second_menu_id) # + else: # + permissions = [] # + context = { 'menu_list': menu_queryset, 'menu_id': menu_id, 'second_menus': second_menus, 'second_menu_id': second_menu_id, 'permissions': permissions # + } return render(request, 'rbac/menu_list.html', context)...# 权限的增删改def permission_add(request, second_menu_id): """ 添加权限 :param request: :param pk: :return: """ if request.method == 'GET': forms = PermissionModelForm() return render(request, 'rbac/change.html', { 'forms': forms}) forms = PermissionModelForm(data=request.POST) if forms.is_valid(): second_menu_obj = models.Permission.objects.filter(id=second_menu_id).first() if not second_menu_obj: return HttpResponse('二级菜单不存在,请重新选择') forms.instance.pid = second_menu_obj # form.instance中包含用户提交的所有值 forms.save() url = memory_reverse(request, 'rbac:menu_list') return redirect(url) return render(request, 'rbac/change.html', { 'forms': forms})def permission_edit(request, pk): """ 权限编辑 :param request: :param pk: 要编辑的权限id :return: """ permission_obj = models.Permission.objects.filter(id=pk).first() if request.method == 'GET': forms = PermissionModelForm(instance=permission_obj) return render(request, 'rbac/change.html', { 'forms': forms}) forms = PermissionModelForm(data=request.POST, instance=permission_obj) if forms.is_valid(): forms.save() url = memory_reverse(request, 'rbac:menu_list') return redirect(url) return render(request, 'rbac/change.html', { 'forms': forms})def permission_del(request, pk): """ 权限删除 :param request: :param pk: :return: """ menu_list_url = memory_reverse(request, 'rbac:menu_list') if request.method == 'GET': return render(request, 'rbac/delete.html', { 'cancel': menu_list_url}) models.Permission.objects.filter(id=pk).delete() return redirect(menu_list_url)
四、模板渲染
rbac/templates/menu_list.html
{% extends 'layout.html' %}{% load rbac %}{% block content %}{% endblock content %}一级菜单 新建
{% for menu in menu_list %} 名称 图标 选项 {% endfor %} { { menu.title }} 二级菜单 {% if menu_id %} 新建 {% endif %}
{% for second_menu in second_menus %} 名称 CODE&URL 选项 { { second_menu.title }} { { second_menu.name }} {% endfor %} { { second_menu.url }} 三级菜单 {% if menu_id %} {% if second_menu_id %} 新建 {% endif %} {% endif %}
{% for permission in permissions %} 名称 CODE&URL 选项 { { permission.title }} { { permission.name }} {% endfor %} { { permission.url }}
需要注意的是选择了一级和二级菜单后才会显示三级菜单的相关信息。增删改页面无需变动。