• 权限组件(9):二级菜单的展示和增删改查


    效果图:

    二级菜单的展示和增删改查

    二级菜单和一级菜单逻辑差不太多。有以下两点需要注意:

    1. 用户不点一级菜单的时候,二级菜单的信息、新建、编辑、删除不会显示
    2. 新建二级菜单的时候,默认选中当前用户选中的一级菜单
    3. 数据库把icon字段的null、blank=True去掉 (需要给已有数据一个默认值)

     

    一、配置URL

    rbac/urls.py

    ...
    from django.urls import re_path
    
    from rbac.views import menu
    ...
    
    urlpatterns = [
        ...
        # 二级菜单
        re_path(r'^second/menu/add/(?P<menu_id>d+)/$', menu.second_menu_add, name='second_menu_add'),
        re_path(r'^second/menu/edit/(?P<pk>d+)/$', menu.second_menu_edit, name='second_menu_edit'),
        re_path(r'^second/menu/del/(?P<pk>d+)/$', menu.second_menu_del, name='second_menu_del'),
        ...
    ]
    

    增加二级菜单需要默认选中一级菜单,所以需要一级菜单的id(在模板层会传入)。

    二、forms表单验证

    forms/base.py

    from django import forms
    
    
    class 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'

    forms/menu.py

    ...
    from rbac import models
    from rbac.forms.base import BaseBootStrapForm
    ...
    
    class SecondMenuModelForm(BaseBootStrapForm):
        class Meta:
            model = models.Permission
            exclude = ['pid'

    三、视图函数

    rbac/veiws/menu.py

    from django.shortcuts import HttpResponse, render, redirect, reverse
    
    from rbac import models
    from rbac.forms.menu import MenuModelForm, SecondMenuModelForm
    from rbac.service.urls import memory_reverse
    
    
    def menu_list(request):
        """
        菜单和权限列表
        :param request:
        :return:
        """
        menu_queryset = models.Menu.objects.all()
    
        menu_id = request.GET.get('mid')  # 用户选择的一级菜单
    
        second_menu_id = request.GET.get('sid')  # 用户选择的二级菜单  +
    
        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 = []
    
        context = {
            'menu_list': menu_queryset,
            'menu_id': menu_id,
            'second_menus': second_menus,
            'second_menu_id': second_menu_id
        }
    
        return render(request, 'rbac/menu_list.html', context)
    
    ...
    # 二级菜单的增删改 def second_menu_add(request, menu_id): """ 增加二级菜单 :param request: :param pk: 已经选择的一级菜单ID(用于设置默认值) :return: """ menu_obj = models.Menu.objects.filter(id=menu_id).first() if request.method == 'GET': forms = SecondMenuModelForm(initial={'menu': menu_obj}) return render(request, 'rbac/change.html', {'forms': forms}) forms = SecondMenuModelForm(data=request.POST) 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 second_menu_edit(request, pk): """ 编辑二级菜单 :param request: :param pk: :return: """ permission_obj = models.Permission.objects.filter(id=pk).first() if request.method == 'GET': forms = SecondMenuModelForm(instance=permission_obj) return render(request, 'rbac/change.html', {'forms': forms}) forms = SecondMenuModelForm(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 second_menu_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 %}
    
    <style>
        tr.active {
            border-left: 3px solid #fdc00f;
        }
    </style>
    
    {% block content %}
        <div class="luffy-container">
            <!-- 一级菜单 -->
            <div class="col-md-3">
                <div class="panel panel-default">
                    <!-- Default panel contents -->
                    <div class="panel-heading">
                        <i class="fa fa-book" aria-hidden="true">一级菜单</i>
                        <a href="{% memory_url request 'rbac:menu_add' %}" class="right btn btn-success btn-xs"
                           style="padding: 2px 8px;margin:-3px">
                            <i class="fa fa-plus-circle" aria-hidden="true">新建</i>
                        </a>
                    </div>
                    <!-- Table -->
                    <table class="table">
                        <thead>
                        <tr>
                            <th>名称</th>
                            <th>图标</th>
                            <th>选项</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for menu in menu_list %}
                            <!-- 管道符可以将后端传来的整型,转换成字符串 -->
                            <tr class="{% if menu.id|safe == menu_id %}active{% endif %}">
                                <td><a href="?mid={{ menu.id }}">{{ menu.title }}</a></td>
                                <td><i class="fa {{ menu.icon }}" aria-hidden="true"></i></td>
                                <td>
                                    <a style="color: #333333; font-size:18px"
                                       href="{% memory_url request 'rbac:menu_edit' pk=menu.id %}">
                                        <i class="fa fa-edit" aria-hidden="true"></i>
                                    </a>
    
                                    <a style="color: red; font-size:18px"
                                       href="{% memory_url request 'rbac:menu_del' pk=menu.id %}">
                                        <i class="fa fa-trash-o" aria-hidden="true"></i>
                                    </a>
                                </td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
    
    
            <!-- 二级菜单 -->
            <div class="col-md-4">
                <div class="panel panel-default">
                    <!-- Default panel contents -->
                    <div class="panel-heading">
                        <i class="fa fa-flag" aria-hidden="true">二级菜单</i>
                        {% if menu_id %}
                            <a href="{% memory_url request 'rbac:second_menu_add' menu_id=menu_id %}"
                               class="right btn btn-success btn-xs"
                               style="padding: 2px 8px;margin:-3px">
                                <i class="fa fa-plus-circle" aria-hidden="true">新建</i>
                            </a>
                        {% endif %}
                    </div>
    
                    <!-- Table -->
                    <table class="table">
                        <thead>
                        <tr>
                            <td>名称</td>
                            <td>CODE&URL</td>
                            <td>选项</td>
                        </tr>
                        </thead>
    
                        <tbody>
                        {% for second_menu in second_menus %}
                            <!-- 管道符可以将后端传来的整型,转换成字符串 -->
                            <tr class="{% if second_menu.id|safe == second_menu_id %}active{% endif %}">
                                <td rowspan="2">
                                    <a href="?mid={{ menu_id }}&sid={{ second_menu.id }}">{{ second_menu.title }}</a>
                                </td>
                                <td>{{ second_menu.name }}</td>
    
                                <td>
                                    <a href="{% memory_url request 'rbac:second_menu_edit' pk=second_menu.id %}"
                                       style="color:#333333;font-size:18px;">
                                        <i class="fa fa-edit" aria-hidden="true"></i>
                                    </a>
    
                                    <a href="{% memory_url request 'rbac:second_menu_del' pk=second_menu.id %}"
                                       style="color:red;font-size:18px;">
                                        <i class="fa fa-trash-o" aria-hidden="true"></i>
                                    </a>
                                </td>
                            </tr>
    
    
                            <tr class="{% if second_menu.id|safe == second_menu_id %}active{% endif %}">
                                <td colspan="2" style="border-top:0;">{{ second_menu.url }}</td>
                            </tr>
    
                        {% endfor %}
    
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    {% endblock content %}

    在总结一下django处理url的流程:在模板层通过反向解析找到url,并把模板层传递的参数传过去,然后到路由层,把request和模板层传过来的参数交给视图函数。

  • 相关阅读:
    华为云发送邮件
    activiti act_re_model 分析
    tengine upstream
    zuul压力测试与调优
    idea 快捷键
    kubernetes helm
    编写高质量代码–改善python程序的建议(二)
    编写高质量代码--改善python程序的建议(一)
    总结OpenvSwitch的调试经验
    提高SDN控制器拓扑发现性能
  • 原文地址:https://www.cnblogs.com/lshedward/p/10506293.html
Copyright © 2020-2023  润新知