后臺菜單管理功能
一、業(yè)務功能分析
1. 業(yè)務需求分析
后臺首頁菜單根據(jù)用戶權限動態(tài)生成葫笼,不同菜單對應不同的功能視圖。菜單的增刪改查哲泊。
2.功能分析
- 菜單列表
- 添加菜單
- 修改菜單
- 刪除菜單
3.模型設計
- 字段分析
- name
- url
- parent
- order
- permission
- icon
- codename
- is_visible
- 模型定義
# 在myadmin/models.py中定義如下模型
from django.db import models
from django.contrib.auth.models import Permission
from utils.models import BaseModel
# Create your models here.
class Menu(BaseModel):
name = models.CharField('菜單名', max_length=48, help_text='菜單名')
url = models.CharField('url', max_length=256, null=True, blank=True, help_text='url')
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
order = models.SmallIntegerField('排序', default=0)
permission = models.OneToOneField(Permission, on_delete=models.SET_NULL, null=True)
icon = models.CharField('圖標', max_length=48, default='fa-link')
codename = models.CharField('權限碼', max_length=48, help_text='權限碼', unique=True)
is_visible = models.BooleanField('是否可見', default=False)
class Meta:
ordering = ['-order']
db_table = 'tb_menu'
verbose_name = '菜單'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
二育特、菜單列表
1.業(yè)務流程分析
- 獲取未刪除,的一級菜單
- 根據(jù)一級菜單獲取未刪除的二級菜單
- 渲染頁面
2.接口設計
- 接口說明
類目 | 說明 |
---|---|
請求方法 | GET |
url定義 | /admin/menus/ |
參數(shù)格式 | 無參數(shù) |
-
返回結果
html
3.后端代碼
- 視圖
# myadmin/views.py下定義如下視圖:
class MenuListView(View):
"""
菜單列表視圖
url:/admin/menus/
"""
def get(self, request):
menus = models.Menu.objects.only('name', 'url', 'icon', 'is_visible', 'order', 'codename').filter(is_delete=False, parent=None)
return render(request, 'myadmin/menu/menu_list.html', context={'menus': menus})
2 . 路由
# admin/urls.py中添加如下路由
path('menus/', views.MenusView.as_view(), name='menu_list'),
4.前端代碼
1.html
<!-- 創(chuàng)建templates/myadmin/menu/menu_list.html-->
{% extends 'myadmin/base/content_base.html' %}
{% load static %}
{% block page_header %}系統(tǒng)設置{% endblock %}
{% block page_option %}菜單管理{% endblock %}
{% block content %}
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">菜單列表</h3>
<div class="box-tools">
<button type="button" class="btn btn-primary btn-sm">添加菜單
</button>
</div>
</div>
<!-- /.box-header -->
<div class="box-body">
<table class="table table-bordered">
<tbody>
<tr>
<th>菜單</th>
<th>子菜單</th>
<th>url</th>
<th>圖標</th>
<th>權限碼</th>
<th>順序</th>
<th>是否可見</th>
<th>邏輯刪除</th>
<th>操作</th>
</tr>
{% for menu in menus %}
<tr>
<td>{{ menu.name }}</td>
<td></td>
<td>{{ menu.url|default:'' }}</td>
<td>{{ menu.icon }}</td>
<td>{{ menu.codename }}</td>
<td>{{ menu.order }}</td>
<td>{% if menu.is_visible %}是{% else %}否{% endif %}</td>
<td style="width: 100px" data-id="{{ menu.id }}" data-name="{{ menu.name }}">
{% if menu.children.all %}
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
{% else %}
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
<button type="button" class="btn btn-danger btn-xs delete">刪除</button>
{% endif %}
</td>
</tr>
{% if menu.children.all %}
{% for child in menu.children.all %}
<tr>
<td></td>
<td>{{ child.name }}</td>
<td>{{ child.url }}</td>
<td>{{ child.icon }}</td>
<td>{{ child.codename }}</td>
<td>{{ child.order }}</td>
<td style="width: 80px">{% if child.is_visible %}是{% else %}否{% endif %}</td>
<td style="width: 100px" data-id="{{ child.id }}" data-name="{{ child.name }}">
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
<button type="button" class="btn btn-danger btn-xs delete">刪除</button>
</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
三先朦、添加菜單頁面
1. 接口設計
- 接口說明:
類目 | 說明 |
---|---|
請求方法 | GET |
url定義 | /admin/menu/ |
參數(shù)格式 | 無參數(shù) |
-
返回數(shù)據(jù)
html
2. 后端代碼
-
視圖
# 在myadmin/views.py中添加如下視圖 class MenuAddView(View): """ 添加菜單視圖 url:/admin/menu/ """ def get(self, request): form = MenuModelForm() return render(request, 'myadmin/menu/add_menu.html', context={'form': form})
-
路由
# 在myadmin/urls.py中添加如下路由 path('menu/', views.MenuAddView.as_view(), name='add_menu')
-
表單
# 在myadmin/forms.py中定義如下表單 from django import forms from .models import Menu class MenuModelForm(forms.ModelForm): parent = forms.ModelChoiceField(queryset=None, required=False, help_text='父菜單') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['parent'].queryset = Menu.objects.filter(is_delete=False, is_visible=True, parent=None) # https://docs.djangoproject.com/en/2.2/ref/forms/fields/#fields-which-handle-relationships class Meta: model = Menu fields = ['name', 'url', 'order', 'parent', 'icon', 'codename', 'is_visible']
為了在渲染表單是能加入自定義css樣式缰冤,在應用admin中定義自定義標簽,在admin下創(chuàng)建templatetags包喳魏,在其中創(chuàng)建admin_customer_tags.py模塊
# myadmin/tamplatetags/admin_customer_tags.py from django.template import Library register = Library() @register.simple_tag() def add_class(field, class_str): return field.as_widget(attrs={'class': class_str})
#### 3.前端代碼
1. html
```html
<!-- 修改 templates/myadmin/menu/menu_list.html -->
{% extends 'myadmin/base/content_base.html' %}
{% load static %}
{% block page_header %}系統(tǒng)設置{% endblock %}
{% block page_option %}菜單管理{% endblock %}
{% block content %}
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">菜單列表</h3>
<div class="box-tools">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#modal-add"
href="{% url 'admin:add_menu' %}">添加菜單
</button>
</div>
</div>
<!-- /.box-header -->
<div class="box-body">
<table class="table table-bordered">
<tbody>
<tr>
<th>菜單</th>
<th>子菜單</th>
<th>url</th>
<th>圖標</th>
<th>權限碼</th>
<th>順序</th>
<th>是否可見</th>
<th>操作</th>
</tr>
{% for menu in menus %}
<tr>
<td>{{ menu.name }}</td>
<td></td>
<td>{{ menu.url|default:'' }}</td>
<td>{{ menu.icon }}</td>
<td>{{ menu.codename }}</td>
<td>{{ menu.order }}</td>
<td>{% if menu.is_visible %}是{% else %}否{% endif %}</td>
<td style="width: 100px" data-id="{{ menu.id }}" data-name="{{ menu.name }}">
{% if menu.children.all %}
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
{% else %}
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
<button type="button" class="btn btn-danger btn-xs delete">刪除</button>
{% endif %}
</td>
</tr>
{% if menu.children.all %}
{% for child in menu.children.all %}
<tr>
<td></td>
<td>{{ child.name }}</td>
<td>{{ child.url }}</td>
<td>{{ child.icon }}</td>
<td>{{ child.codename }}</td>
<td>{{ child.order }}</td>
<td style="width: 80px">{% if child.is_visible %}是{% else %}否{% endif %}</td>
<td style="width: 100px" data-id="{{ child.id }}" data-name="{{ child.name }}">
<button type="button" class="btn btn-info btn-xs edit">編輯</button>
<button type="button" class="btn btn-danger btn-xs delete">刪除</button>
</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- add modle -->
<div class="modal fade" id="modal-add" role="dialog" >
<div class="modal-dialog">
<div class="modal-content">
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
{% endblock %}
<!-- 新建 templates/myadmin/menu/add_menu.html -->
{% load admin_customer_tags %}
{% load static %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">添加菜單</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" id="add-menu">
{% csrf_token %}
<div class="box-body">
{% for field in form %}
{% if field.name == 'is_visible' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label for="{{ field.id_for_label }}">{{ field }}{{ field.label }}</label>
</div>
</div>
</div>
{% else %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
<label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-10">
{% for error in field.errors %}
<label class="control-label" for="{{ field.id_for_label }}">{{ error }}</label>
{% endfor %}
{% add_class field 'form-control' %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary add">添加</button>
</div>
四棉浸、添加菜單
1.業(yè)務流程分析
- 接收表單參數(shù)
- 校驗表單參數(shù)
- 校驗成功保存菜單數(shù)據(jù),創(chuàng)建菜單一對一關聯(lián)權限對象刺彩,返回創(chuàng)建成功的json數(shù)據(jù)
- 校驗失敗迷郑,返回渲染了錯誤信息的表單
2.接口設計
- 接口說明:
類目 | 說明 |
---|---|
請求方法 | POST |
url定義 | /admin/menu/ |
參數(shù)格式 | 表單參數(shù) |
- 參數(shù)說明:
參數(shù)名 | 類型 | 是否必須 | 描述 |
---|---|---|---|
name | 字符串 | 是 | 菜單名 |
url | 字符串 | 否 | 當前文章頁數(shù) |
order | 整數(shù) | 是 | 排序 |
parent | 整數(shù) | 否 | 父菜單id |
icon | 字符串 | 是 | 渲染圖標類名 |
codename | 字符串 | 是 | 權限碼 |
is_visible | 整數(shù) | 是 | 是否可見 |
-
返回數(shù)據(jù)
# 添加正常返回json數(shù)據(jù) { "errno": "0", "errmsg": "菜單添加成功!" }
如果有錯誤创倔,返回html表單
3.后端代碼
-
視圖
# 在myadmin/views.py中的MenuAddView視圖中添加post方法 class MenuAddView(View): """ 添加菜單視圖 url:/admin/menu/ """ def get(self, request): form = MenuModelForm() return render(request, 'myadmin/menu/add_menu.html', context={'form': form}) def post(self, request): form = MenuModelForm(request.POST) if form.is_valid(): new_menu = form.save() content_type = ContentType.objects.filter(app_label='myadmin', model='menu').first() permission = Permission.objects.create(name=new_menu.name, content_type=content_type, codename=new_menu.codename) new_menu.permission = permission new_menu.save(update_fields=['permission']) return json_response(errmsg='菜單添加成功嗡害!') else: return render(request, 'myadmin/menu/add_menu.html', context={'form': form})
4.前端代碼
-
html
<!-- 在 templates/myadmin/menu/add_menu.html 中引入js --> ... <script src="{% static 'js/myadmin/menu/add_menu.js' %}"></script>
-
js
// 創(chuàng)建static/js/myadmin/menu/add_menu.js $(() => { let $addBtn = $('button.add'); // 模態(tài)框中的添加按鈕 let $form = $('#add-menu'); // 模態(tài)礦中的表單 let data = {}; $addBtn.click(function () { $ .ajax({ url: '/admin/menu/', type: 'POST', data: $form.serialize(), // dataType: "json" }) .done((res) => { if (res.errno === '0') { // 添加成功,關閉模態(tài)框三幻,并刷新菜單列表 $('#modal-add').modal('hide').on('hidden.bs.modal', function (e) { $('#content').load( $('.sidebar-menu li.active a').data('url'), (response, status, xhr) => { if (status !== 'success') { message.showError('服務器超時就漾,請重試!') } } ); }); message.showSuccess(res.errmsg); } else { message.showError('添加菜單失斈畎帷!'); // 更新模特框中的表單信息 $('#modal-add .modal-content').html(res) } }) .fail(() => { message.showError('服務器超時摆出,請重試'); }); }); });
五朗徊、刪除菜單
1.接口設計
- 接口說明:
類目 | 說明 |
---|---|
請求方法 | DELETE |
url定義 | /admin/menu/<int:menu_id>/ |
參數(shù)格式 | 路徑參數(shù) |
- 參數(shù)說明
參數(shù)名 | 類型 | 是否必須 | 描述 |
---|---|---|---|
menu_id | 整數(shù) | 是 | 菜單id |
-
返回值
{ "errno": "0", "errmsg": "刪除菜單成功!" }
2.后端代碼
-
視圖
# 在admin/views.py中創(chuàng)建一個MenuUpdateView視圖 class MenuUpdateView(View): """ 菜單管理視圖 url:/admin/menu/<int:menu_id>/ """ def delete(self, request, menu_id): menu = models.Menu.objects.filter(is_delete=False, id=menu_id) if menu: menu = menu[0] if menu.children.filter(is_delete=False).exists(): return json_response(errno=Code.DATAERR, errmsg='父菜單不能刪除偎漫!') menu.is_delete = True menu.save(update_fields=['is_delete']) return json_response() else: return json_response(errno=Code.NODATA, errmsg='菜單不存在爷恳!')
-
路由
# 在admin/urls.py中添加如下路由 path('menu/<int:menu_id>/', views.MenuUpdateView.as_view(), name='menu_manage'),
3.前端代碼
-
html
<!-- 修改 templates/admin/menu/menu_list.html 在content中,添加刪除模態(tài)框 然后引入menu.js --> {% block content %} ... ... <div class="modal modal-danger fade" id="modal-delete"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span></button> <h4 class="modal-title">警告</h4> </div> <div class="modal-body"> <p>One fine body…</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-outline pull-left" data-dismiss="modal">取消</button> <button type="button" class="btn btn-outline delete-confirm">刪除</button> </div> </div> <!-- /.modal-content --> </div> <!-- /.modal-dialog --> </div> <!-- /.modal --> {% endblock %} {% block script %} <script src="{% static 'js/admin/menu/menu.js' %}"></script> {% endblock %}
-
js
// 創(chuàng)建 static/js/admin/menu/menu.js $(() => { let $editBtns = $('button.edit'); let $deleteBtns = $('button.delete'); // 刪除按鈕 menuId = 0; // 被點擊菜單id let $currentMenu = null; // 當前被點擊菜單對象 $deleteBtns.click(function () { let $this = $(this); $currentMenu = $this.parent().parent(); menuId = $this.parent().data('id'); let menuName = $this.parent().data('name'); $('#modal-delete .modal-body p').html('確定刪除菜單:《' + menuName + '》?'); $('#modal-delete').modal('show'); $('#modal-delete button.delete-confirm').click(() => { deleteMenu(); }) }); // 刪除菜單 function deleteMenu() { $ .ajax({ url: '/admin/menu/' + menuId + '/', type: 'DELETE', dataType: "json" }) .done((res) => { if (res.errno === '0') { $('#modal-delete').modal('hide'); $('#modal-delete button.delete-confirm').unbind(); $currentMenu.remove(); message.showSuccess('刪除成功象踊!'); } else { message.showError(res.errmsg) } }) .fail(() => { message.showError('服務器超時温亲,請重試!') }); } });
六杯矩、編輯菜單頁面
1. 接口設計
- 接口說明:
類目 | 說明 |
---|---|
請求方法 | GET |
url定義 | /admin/menu/<int:menu_id> |
參數(shù)格式 | 路徑參數(shù) |
- 參數(shù)說明
參數(shù)名 | 類型 | 是否必須 | 描述 |
---|---|---|---|
menu_id | 整數(shù) | 是 | 菜單id |
-
返回數(shù)據(jù)
html
2.后端代碼
# 在admin/views.py中的MenuUpdateView視圖中添加一個get方法
class MenuUpdateView(View):
"""
菜單管理視圖
url:/admin/menu/<int:menu_id>/
"""
def get(self, request, menu_id):
menu = models.Menu.objects.filter(is_delete=False, id=menu_id).first()
form = MenuModelForm(instance=menu)
return render(request, 'admin/menu/update_menu.html', context={'form': form})
3.前端代碼
-
html
<!-- 修改 templates/admin/menu/menu_list.html 在content中栈虚,添加修改模態(tài)框 --> {% block content %} ... <!-- update modle --> <div class="modal fade" id="modal-update" role="dialog" aria-labelledby="myLargeModalLabel"> <div class="modal-dialog"> <div class="modal-content"> </div> <!-- /.modal-content --> </div> <!-- /.modal-dialog --> </div> <!-- /.modal --> {% endblock %}
<!-- 新建 templates/admin/menu/update_menu.html --> {% load admin_customer_tags %} {% load static %} <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span></button> <h4 class="modal-title">修改菜單</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="update-menu"> {% csrf_token %} <div class="box-body"> {% for field in form %} {% if field.name == 'is_visible' %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label for="{{ field.id_for_label }}">{{ field }}{{ field.label }}</label> </div> </div> </div> {% else %} <div class="form-group {% if field.errors %}has-error{% endif %}"> <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {% for error in field.errors %} <label class="control-label" for="{{ field.id_for_label }}">{{ error }}</label> {% endfor %} {% add_class field 'form-control' %} </div> </div> {% endif %} {% endfor %} </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default pull-left" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary update">修改</button> </div>
-
js
// 修改 static/js/admin/menu/menu.js $(() => { let $editBtns = $('button.edit'); let $deleteBtns = $('button.delete'); // 刪除按鈕 menuId = 0; // 被點擊菜單id let $currentMenu = null; // 當前被點擊菜單對象 // 編輯菜單 $editBtns.click(function () { let $this = $(this); $currentMenu = $this.parent().parent(); menuId = $this.parent().data('id'); $ .ajax({ url: '/admin/menu/'+ menuId +'/', type: 'get' }) .done((res)=>{ $('#modal-update .modal-content').html(res); $('#modal-update').modal('show') }) .fail(()=>{ message.showError('服務器超時,請重試史隆!') }) }); $deleteBtns.click(function () { let $this = $(this); $currentMenu = $this.parent().parent(); menuId = $this.parent().data('id'); let menuName = $this.parent().data('name'); $('#modal-delete .modal-body p').html('確定刪除菜單:《' + menuName + '》?'); $('#modal-delete').modal('show'); $('#modal-delete button.delete-confirm').click(() => { deleteMenu(); }) }); // 刪除菜單 function deleteMenu() { $ .ajax({ url: '/admin/menu/' + menuId + '/', type: 'DELETE', dataType: "json" }) .done((res) => { if (res.errno === '0') { $('#modal-delete').modal('hide'); $('#modal-delete button.delete-confirm').unbind(); $currentMenu.remove(); message.showSuccess('刪除成功魂务!'); } else { message.showError(res.errmsg) } }) .fail(() => { message.showError('服務器超時,請重試!') }); } });
七粘姜、編輯菜單
1.業(yè)務流程分析
- 接收表單參數(shù)
- 校驗表單參數(shù)
- 校驗成功保存菜單鬓照,判斷改動字段是否影響了權限,如果有影響孤紧,修改權限豺裆,返回json信息
- 校驗失敗,返回包含錯誤信息的html
2.接口設計
- 接口說明:
類目 | 說明 |
---|---|
請求方法 | PUT |
url定義 | /admin/menu/<int:menu_id> |
參數(shù)格式 | 路徑參數(shù)+表單參數(shù) |
- 參數(shù)說明:
參數(shù)名 | 類型 | 是否必須 | 描述 |
---|---|---|---|
menu_id | 整數(shù) | 是 | 菜單id |
name | 字符串 | 是 | 菜單名 |
url | 字符串 | 否 | 當前文章頁數(shù) |
order | 整數(shù) | 是 | 排序 |
parent | 整數(shù) | 否 | 父菜單id |
icon | 字符串 | 是 | 渲染圖標類名 |
codename | 字符串 | 是 | 權限碼 |
is_visible | 整數(shù) | 是 | 是否可見 |
-
返回數(shù)據(jù)
# 添加正常返回json數(shù)據(jù) { "errno": "0", "errmsg": "菜單修改成功号显!" }
如果有錯誤留储,返回html表單
3.后端代碼
-
視圖
# 在admin/views.py中的MenuUpdateView視圖中添加一個put方法 class MenuUpdateView(View): """ 菜單管理視圖 url:/admin/menu/<int:menu_id>/ """ ... def put(self, request, menu_id): menu = models.Menu.objects.filter(is_delete=False, id=menu_id).first() put = QueryDict(request.body) form = MenuModelForm(put, instance=menu) if form.is_valid(): obj = form.save() if 'name' in form.changed_data: obj.permission.name = obj.name if 'codename' in form.changed_data: obj.permission.codename = obj.codename obj.permission.save() return json_response(errmsg='菜單修改成功!') else: return render(request, 'admin/menu/update_menu.html', context={'form': form}) ...
4.前端代碼
- html
<!-- 在 templates/admin/menu/update_menu.html
中引入update_menu.js
-->
...
<script src="{% static 'js/admin/menu/update_menu.js' %}"></script>
-
js
$(()=>{ let $updateBtn = $('#modal-update button.update'); let $form = $('#update-menu'); let data = {}; $updateBtn.click(function () { $.each($form.serializeArray(), function () { data[this.name] = this.value }); $ .ajax({ url: '/admin/menu/' + menuId + '/', type: 'PUT', data: data, // dataType: "json" }) .done((res) => { if (res.errno === '0') { $('#modal-update').modal('hide').on('hidden.bs.modal', function (e) { $('#content').load( $('.sidebar-menu li.active a').data('url'), (response, status, xhr) => { if (status !== 'success') { message.showError('服務器超時咙轩,請重試获讳!') } } ); }); message.showSuccess(res.errmsg); } else { message.showError('修改菜單失敗活喊!'); $('#modal-update .modal-content').html(res) } }) .fail(() => { message.showError('服務器超時丐膝,請重試'); }); }); });
八、整合后臺首頁面菜單加載
1. 后端代碼
-
視圖
class IndexView(LoginRequiredMixin, View): """ 后臺首頁視圖 """ def get(self, request): objs = models.Menu.objects.only('name', 'url', 'icon', 'permission__codename', 'permission__content_type__app_label').select_related( 'permission__content_type').filter(is_delete=False, is_visible=True, parent=None) has_permissions = request.user.get_all_permissions() menus = [] for menu in objs: if '%s.%s' % (menu.permission.content_type.app_label, menu.permission.codename) in has_permissions: temp = { 'name': menu.name, 'icon': menu.icon } children = menu.children.filter(is_delete=False, is_visible=True) if children: temp['children'] = [] for child in children: if '%s.%s' % (child.permission.content_type.app_label, child.permission.codename) in has_permissions: temp['children'].append({ 'name': child.name, 'url': child.url }) else: if not menu.url: continue temp['url'] = menu.url menus.append(temp) print(menus) return render(request, 'admin/index.html', context={'menus': menus})