4 权限分配
给用户进行权限的分配。
1 角色管理
项目目录下urls新增一条url
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^rbac/', include('rbac.urls', namespace="rbac")),
url(r'^', include('web.urls')),
]
rbac的app中新建urls.py文件
from django.conf.urls import url
from rbac.views import role
urlpatterns = [
url(r"^role/list/$", role.role_list, name="role_list"),
url(r"^role/add/$", role.role_add, name="role_add"),
url(r"^role/edit/(?P<pk>\d+)/$", role.role_edit, name="role_edit"),
url(r"^role/del/(?P<pk>\d+)/$", role.role_del, name="role_del"),
]
app_name = "rbac"
rbac的app中views/role.py文件
role.py
from django.shortcuts import render, redirect, HttpResponse
from django.urls import reverse
from django import forms
from rbac import models
class RoleModelForm(forms.ModelForm):
class Meta:
model = models.Role
fields = ["title"]
widgets = {
"title": forms.TextInput(attrs={"class": "form-control"})
}
def role_list(request):
"""角色列表"""
role_queryset = models.Role.objects.all()
return render(request, "rbac/role_list.html", {"roles": role_queryset})
def role_add(request):
"""添加角色"""
if request.method == "GET":
form = RoleModelForm()
return render(request, "rbac/change.html", {"form": form})
form = RoleModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse("rbac:role_list"))
return render(request, "rbac/change.html", {"form": form})
def role_edit(request, pk):
"""编辑角色"""
obj = models.Role.objects.filter(id=pk).first()
if not obj:
return HttpResponse("角色不存在")
if request.method == "GET":
form = RoleModelForm(instance=obj)
return render(request, "rbac/change.html", {"form": form})
form = RoleModelForm(instance=obj, data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse("rbac:role_list"))
return render(request, "rbac/change.html", {"form": form})
def role_del(request, pk):
"""删除角色"""
origin_url = reverse("rbac:role_list")
if request.method == "GET":
return render(request, "rbac/delete.html", {"cancel_url": origin_url})
models.Role.objects.filter(id=pk).delete()
return redirect(origin_url)
rbac的app中templates/rbac/xxx.html文件
role_list.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<div class="btn-group" style="margin: 5px 0">
<a class="btn btn-default" href="{% url "rbac:role_add" %}">
<i class="fa fa-plus-square" aria-hidden="true"></i> 添加角色
</a>
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in roles %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td>
<a style="color: #333333;" href="{% url "rbac:role_edit" pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% url "rbac:role_del" pk=row.id %}"><i
class="fa fa-trash-o"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
change.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<form class="form-horizontal" action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="" class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-8">
{{ field }}
<span style="color: red">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<input type="submit" value="保存" class="btn btn-primary">
</div>
</div>
</form>
</div>
{% endblock %}
delete.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<div class="alert alert-danger" role="alert">
<form method="post">
{% csrf_token %}
<p style="font-size: 13px"><i class="fa fa-warning" aria-hidden="true"></i> 删除后不可恢复,是否确认删除!</p>
<div style="margin-top: 20px">
<a href="{{ cancel_url }}" class="btn btn-default btn-sm">取消</a>
<button type="submit" class="btn btn-danger btn-sm">确认</button>
</div>
</form>
</div>
</div>
{% endblock %}
点击下载代码
2 用户管理
rbac的app中新建urls.py文件
from django.conf.urls import url
from rbac.views import role, user
urlpatterns = [
...
url(r"^user/list/$", user.user_list, name="user_list"),
url(r"^user/add/$", user.user_add, name="user_add"),
url(r"^user/edit/(?P<pk>\d+)/$", user.user_edit, name="user_edit"),
url(r"^user/del/(?P<pk>\d+)/$", user.user_del, name="user_del"),
]
app_name = "rbac"
rbac的app中myforms/user.py文件
user.py
from django import forms
from django.core.exceptions import ValidationError
from rbac import models
class UserModelForm(forms.ModelForm):
re_password = forms.CharField(label="确认密码")
class Meta:
model = models.UserInfo
fields = ["name", "email", "password", "re_password"]
def __init__(self, *args, **kwargs):
# 统一给form字段添加bootstrap样式
super(UserModelForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs["class"] = "form-control"
def clean_re_password(self):
password = self.cleaned_data["password"]
re_password = self.cleaned_data["re_password"]
if password != re_password:
raise ValidationError("两次密码不一致")
return re_password
class UpdateUserModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "email"]
def __init__(self, *args, **kwargs):
super(UpdateUserModelForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs["class"] = "form-control"
class ResetPasswordModelForm(forms.ModelForm):
re_password = forms.CharField(label="确认密码")
class Meta:
model = models.UserInfo
fields = ["password", "re_password"]
def __init__(self, *args, **kwargs):
super(ResetPasswordModelForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs["class"] = "form-control"
def clean_re_password(self):
password = self.cleaned_data["password"]
re_password = self.cleaned_data["re_password"]
if password != re_password:
raise ValidationError("两次密码不一致")
return self.re_password
rbac的app中views/user.py文件
user.py
from django.shortcuts import render, redirect, HttpResponse
from django.urls import reverse
from rbac import models
from rbac.my_forms.user import UserModelForm, UpdateUserModelForm, ResetPasswordModelForm
def user_list(request):
"""用户列表"""
user_queryset = models.UserInfo.objects.all()
return render(request, "rbac/user_list.html", {"users": user_queryset})
def user_add(request):
"""添加用户"""
if request.method == "GET":
form = UserModelForm()
return render(request, "rbac/change.html", {"form": form})
form = UserModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse("rbac:user_list"))
return render(request, "rbac/change.html", {"form": form})
def user_edit(request, pk):
"""编辑用户"""
obj = models.UserInfo.objects.filter(id=pk).first()
if not obj:
return HttpResponse("用户不存在")
if request.method == "GET":
form = UpdateUserModelForm(instance=obj)
return render(request, "rbac/change.html", {"form": form})
form = UpdateUserModelForm(instance=obj, data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse("rbac:user_list"))
return render(request, "rbac/change.html", {"form": form})
def reset_pwd(request, pk):
"""重置密码"""
obj = models.UserInfo.objects.filter(id=pk).first()
if not obj:
return HttpResponse("用户不存在")
if request.method == "GET":
form = ResetPasswordModelForm()
return render(request, "rbac/change.html", {"form": form})
form = ResetPasswordModelForm(instance=obj, data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse("rbac:user_list"))
return render(request, "rbac/change.html", {"form": form})
def user_del(request, pk):
"""删除用户"""
origin_url = reverse("rbac:user_list")
if request.method == "GET":
return render(request, "rbac/delete.html", {"cancel_url": origin_url})
models.UserInfo.objects.filter(id=pk).delete()
return redirect(origin_url)
rbac的app中templates/rbac/xxx.html文件
user_list.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<div class="btn-group" style="margin: 5px 0">
<a class="btn btn-default" href="{% url "rbac:user_add" %}">
<i class="fa fa-plus-square" aria-hidden="true"></i> 添加用户
</a>
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>序号</th>
<th>用户名</th>
<th>邮箱</th>
<th>重置密码</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in users %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.name }}</td>
<td>{{ row.email }}</td>
<td>
<a href="{% url "rbac:user_reset_pwd" pk=row.id %}">重置密码</a>
</td>
<td>
<a style="color: #333333;" href="{% url "rbac:user_edit" pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% url "rbac:user_del" pk=row.id %}"><i
class="fa fa-trash-o"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
change.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<form class="form-horizontal" action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="" class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-8">
{{ field }}
<span style="color: red">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<input type="submit" value="保存" class="btn btn-primary">
</div>
</div>
</form>
</div>
{% endblock %}
delete.html
{% extends "layout.html" %}
{% block content %}
<div class="luffy-container">
<div class="alert alert-danger" role="alert">
<form method="post">
{% csrf_token %}
<p style="font-size: 13px"><i class="fa fa-warning" aria-hidden="true"></i> 删除后不可恢复,是否确认删除!</p>
<div style="margin-top: 20px">
<a href="{{ cancel_url }}" class="btn btn-default btn-sm">取消</a>
<button type="submit" class="btn btn-danger btn-sm">确认</button>
</div>
</form>
</div>
</div>
{% endblock %}
点击下载代码
3 菜单和权限的管理
3-1 一级菜单
urls.py
from django.conf.urls import url
from rbac.views import menu
urlpatterns = [
...
url(r'^menu/list/$', menu.menu_list, name='menu_list'),
url(r'^menu/add/$', menu.menu_add, name='menu_add'),
url(r'^menu/edit/(?P<pk>\d+)/$', menu.menu_edit, name='menu_edit'),
url(r'^menu/del/(?P<pk>\d+)/$', menu.menu_del, name='menu_del'),
]
app_name = "rbac"
menu.py视图
from django.shortcuts import render, redirect, HttpResponse
from django.urls import reverse
from rbac import models
from rbac.forms.menu import MenuModelForm
from rbac.service.urls import memory_reverse
def menu_list(request):
"""菜单和权限列表"""
menus = models.Menu.objects.all()
menu_id = request.GET.get("mid")
menu_dict = {
"menus": menus,
"menu_id": menu_id,
}
return render(request, "rbac/menu_list.html", menu_dict)
def menu_add(request):
if request.method == 'GET':
form = MenuModelForm()
return render(request, 'rbac/change.html', {'form': form})
form = MenuModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def menu_edit(request, pk):
obj = models.Menu.objects.filter(id=pk).first()
if not obj:
return HttpResponse('菜单不存在')
if request.method == 'GET':
form = MenuModelForm(instance=obj)
return render(request, 'rbac/change.html', {'form': form})
form = MenuModelForm(instance=obj, data=request.POST)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def menu_del(request, pk):
url = memory_reverse(request, "rbac:menu_list")
if request.method == 'GET':
return render(request, 'rbac/delete.html', {'cancel': url})
models.Menu.objects.filter(id=pk).delete()
return redirect(url)
menu.py-fomrs
from django import forms
from django.utils.safestring import mark_safe
from rbac import models
class MenuModelForm(forms.ModelForm):
class Meta:
model = models.Menu
fields = ["title", "icon"]
widgets = {
"title": forms.TextInput(attrs={"class": "form-control"}),
"icon": forms.RadioSelect(choices=[
["fa-area-chart", mark_safe('<i class="fa fa-area-chart" aria-hidden="true"></i>')],
["fa-bicycle", mark_safe('<i class="fa fa-bicycle" aria-hidden="true"></i>')],
["fa-bolt", mark_safe('<i class="fa fa-bolt" aria-hidden="true"></i>')],
["fa-battery-3", mark_safe('<i class="fa fa-battery-3" aria-hidden="true"></i>')]
], attrs={"class": "clearfix"})
}
rbac.py
@register.simple_tag()
def memory_url(request, name, *args, **kwargs):
return urls.memory_url(request, name, *args, **kwargs)
service/urls.py
from django.urls import reverse
from django.http import QueryDict
def memory_url(request, name, *args, **kwargs):
"""生成带有原搜索条件的url,替代了模板中的url"""
basic_url = reverse(name, args=args, kwargs=kwargs)
if not request.GET:
return basic_url
query_dict = QueryDict(mutable=True) # 可修改
query_dict["_filter"] = request.GET.urlencode() # mid=1&age=2
return "{}?{}".format(basic_url, query_dict.urlencode()) # /menu/list/?_filter=mid%3D1
def memory_reverse(request, name, *args, **kwargs):
"""反向生成url"""
url = reverse(name, args=args, kwargs=kwargs)
origin_params = request.GET.get("_filter")
if origin_params:
url = "{}?{}".format(url, origin_params)
return url
模板
{% extends 'layout.html' %}
{% block css %}
<style>
ul{
list-style-type: none;
padding: 0;
}
ul li{
float: left;
padding: 10px;
padding-left: 0;
width: 80px;
}
ul li i{
font-size: 18px;
margin-left: 5px;
color: #6d6565;
}
</style>
{% endblock %}
{% block content %}
<div class="luffy-container">
<form class="form-horizontal" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-8">
{{ field }}
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<input type="submit" value="保 存" class="btn btn-primary">
</div>
</div>
</form>
</div>
{% endblock %}
一级菜单代码下载
3-2 二级菜单
urls.py
from django.conf.urls import url
from rbac.views import menu
urlpatterns = [
...
url(r'^second/menu/add/(?P<menu_id>\d+)/$', menu.second_menu_add, name='second_menu_add'),
url(r'^second/menu/edit/(?P<pk>\d+)/$', menu.second_menu_edit, name='second_menu_edit'),
url(r'^second/menu/del/(?P<pk>\d+)/$', menu.second_menu_del, name='second_menu_del'),
]
app_name = "rbac"
menu.py视图
from django.shortcuts import render, redirect, HttpResponse
from rbac import models
from rbac.forms.menu import MenuModelForm, SecondModelForm
from rbac.service.urls import memory_reverse
def second_menu_add(request, menu_id):
"""新增二级菜单"""
menu_obj = models.Menu.objects.filter(id=menu_id).first()
if request.method == 'GET':
form = SecondModelForm(initial={"menu": menu_obj})
return render(request, 'rbac/change.html', {'form': form})
form = SecondModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def second_menu_edit(request, pk):
"""编辑二级菜单"""
permission_obj = models.Permission.objects.filter(id=pk).first()
if request.method == 'GET':
form = SecondModelForm(instance=permission_obj)
return render(request, 'rbac/change.html', {'form': form})
form = SecondModelForm(data=request.POST, instance=permission_obj)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def second_menu_del(request, pk):
url = memory_reverse(request, "rbac:menu_list")
if request.method == 'GET':
return render(request, 'rbac/delete.html', {'cancel': url})
models.Permission.objects.filter(id=pk).delete()
return redirect(url)
menu.py-forms
class BootStrapModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BootStrapModelForm, self).__init__(*args, **kwargs)
# 统一给ModelForm生成字段添加样式
for name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
class SecondModelForm(BootStrapModelForm):
class Meta:
model = models.Permission
exclude = ["pid"]
rbac.py 参考一级菜单
service/urls.py 参考一级菜单
模板
{% extends 'layout.html' %}
{% load rbac %}
{% block css %}
<style>
tr.active {
border-left: 3px solid #fdc00f;
}
</style>
{% endblock %}
{% 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-pause-circle" aria-hidden="true"></i> 新建
</a>
</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>图标</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in menus %}
<tr class="{% if row.id|safe == menu_id %}active{% endif %}">
<td><a href="?mid={{ row.id }}">{{ row.title }}</a></td>
<td><i class="fa {{ row.icon }}" aria-hidden="true"></i></td>
<td>
<a style="color: #333333;" href="{% memory_url request "rbac:menu_edit" pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% memory_url request "rbac:menu_del" pk=row.id %}"><i
class="fa fa-trash-o"></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-bars" 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-pause-circle" aria-hidden="true"></i> 新建
</a>
{% endif %}
</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>CODE & URL</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in second_menus %}
<tr class="{% if row.id|safe == second_menu_id %}active{% endif %}">
<td rowspan="2"><a href="?mid={{ menu_id }}&sid={{ row.id }}">{{ row.title }}</a></td>
<td>{{ row.name }}</td>
<td>
<a style="color: #333333;" href="{% memory_url request 'rbac:second_menu_edit' pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% memory_url request 'rbac:second_menu_del' pk=row.id %}"><i
class="fa fa-trash-o"></i></a>
</td>
</tr>
<tr class="{% if row.id|safe == second_menu_id %}active{% endif %}">
<td colspan="2" style="border-top: 0">{{ row.url }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
二级菜单代码下载
4 权限的展示
urls.py
from django.conf.urls import url
from rbac.views import menu
urlpatterns = [
...
url(r'^permission/add/(?P<second_menu_id>\d+)/$', menu.permission_add, name='permission_add'),
url(r'^permission/edit/(?P<pk>\d+)/$', menu.permission_edit, name='permission_edit'),
url(r'^permission/del/(?P<pk>\d+)/$', menu.permission_del, name='permission_del'),
]
app_name = "rbac"
menu.py视图
class PermissionModelrForm(BootStrapModelForm):
class Meta:
model = models.Permission
fields = ["title", "name", "url"]
def permission_add(request, second_menu_id):
"""添加权限"""
if request.method == 'GET':
form = PermissionModelrForm()
return render(request, 'rbac/change.html', {'form': form})
form = PermissionModelrForm(data=request.POST)
if form.is_valid():
second_menu_obj = models.Permission.objects.filter(id=second_menu_id).first()
if not second_menu_obj:
return HttpResponse("二级菜单不存在")
form.instance.pid = second_menu_obj
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def permission_edit(request, pk):
"""编辑二级菜单"""
permission_obj = models.Permission.objects.filter(id=pk).first()
if request.method == 'GET':
form = PermissionModelrForm(instance=permission_obj)
return render(request, 'rbac/change.html', {'form': form})
form = PermissionModelrForm(data=request.POST, instance=permission_obj)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, "rbac:menu_list"))
return render(request, 'rbac/change.html', {'form': form})
def permission_del(request, pk):
url = memory_reverse(request, "rbac:menu_list")
if request.method == 'GET':
return render(request, 'rbac/delete.html', {'cancel': url})
models.Permission.objects.filter(id=pk).delete()
return redirect(url)
rbac.py 参考一级菜单
service/urls.py 参考一级菜单
模板
{% extends 'layout.html' %}
{% load rbac %}
{% block css %}
<style>
tr.active {
border-left: 3px solid #fdc00f;
}
</style>
{% endblock %}
{% 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-pause-circle" aria-hidden="true"></i> 新建
</a>
</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>图标</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in menus %}
<tr class="{% if row.id|safe == menu_id %}active{% endif %}">
<td><a href="?mid={{ row.id }}">{{ row.title }}</a></td>
<td><i class="fa {{ row.icon }}" aria-hidden="true"></i></td>
<td>
<a style="color: #333333;" href="{% memory_url request "rbac:menu_edit" pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% memory_url request "rbac:menu_del" pk=row.id %}"><i
class="fa fa-trash-o"></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-bars" 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-pause-circle" aria-hidden="true"></i> 新建
</a>
{% endif %}
</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>CODE & URL</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in second_menus %}
<tr class="{% if row.id|safe == second_menu_id %}active{% endif %}">
<td rowspan="2"><a href="?mid={{ menu_id }}&sid={{ row.id }}">{{ row.title }}</a></td>
<td>{{ row.name }}</td>
<td>
<a style="color: #333333;" href="{% memory_url request 'rbac:second_menu_edit' pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% memory_url request 'rbac:second_menu_del' pk=row.id %}"><i
class="fa fa-trash-o"></i></a>
</td>
</tr>
<tr class="{% if row.id|safe == second_menu_id %}active{% endif %}">
<td colspan="2" style="border-top: 0">{{ row.url }}</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-bars" aria-hidden="true"></i> 权限
{% if second_menu_id %}
<a href="{% memory_url request 'rbac:permission_add' second_menu_id=second_menu_id %}" class="right btn btn-success btn-xs" style="padding: 2px 8px;margin: -3px">
<i class="fa fa-pause-circle" aria-hidden="true"></i> 新建
</a>
{% endif %}
</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>CODE & URL</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in permissions %}
<tr>
<td rowspan="2">{{ row.title }}</td>
<td>{{ row.name }}</td>
<td>
<a style="color: #333333;" href="{% memory_url request 'rbac:permission_edit' pk=row.id %}">
<i class="fa fa-edit" aria-hidden="true"></i></a>
<a style="color: #d9534f;" href="{% memory_url request 'rbac:permission_del' pk=row.id %}"><i
class="fa fa-trash-o"></i></a>
</td>
</tr>
<tr>
<td colspan="2" style="border-top: 0">{{ row.url }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
三级菜单代码下载