1.实现思路
![]()
2.代码部分
关于app01views部分,主要是写login权限
from django.shortcuts import render, HttpResponse
from rbac.models import UserInfo
from django.http import JsonResponse
# Create your views here.
def login(request):
if request.method == 'GET': # 如果是GET请求(第一次)进来,则是登陆界面
return render(request, 'login.html')
else:
res = {'user': None, 'msg': ""} # 设置默认回复
user = request.POST.get('user') # ajax请求
pwd = request.POST.get('pwd')
user_obj = UserInfo.objects.filter(name=user, pwd=pwd).first() # 与数据库做校验获取到对象
if user_obj:
request.session['user_id'] = user_obj.pk # 注册登陆用户的ID
request.session['user_name'] = user_obj.name # 注册登陆用户的ID
# 获取用户权限并去重
permissions = user_obj.roles.all().values('permissions__url',
'permissions__title',
'permissions__pk',
'permissions__type',
'permissions__parent_id',
).distinct()
permission_list = [] # 将用户的权限写在列表并放回到给用户的session里,此时用户就可以带着自己的session请求别的
for permission in permissions:
permission_list.append({
'url': permission['permissions__url'],
'title': permission['permissions__title'],
'pk': permission['permissions__pk'],
'type': permission['permissions__type'],
'pid': permission['permissions__parent_id'],
})
print("permission_list----->", permission_list)
# 将权限列表放入session中
request.session['permission_list'] = permission_list
res['user'] = user_obj.name
else:
res['msg'] = '用户名或密码错误!'
return JsonResponse(res) # 改返回方法可以让前端的ajax默认解析json格式,传递是需要json格式的
# 关于rbac里面的中间件部分
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/', '/reg/', '/admin/*']:
permission_url = '^%s$' % reg
ret = re.search(permission_url, current_path)
if ret:
return None
# 校验是否登陆
user_id = request.session.get('user_id')
if not user_id:
return redirect('/login/')
# 当前用户所有的权限列表,并比较当前路径里的session跟现要访问的路径是否一致
permission_list = request.session.get('permission_list')
for permission in permission_list:
permission_url = permission.get('url') # 拿出url,因为是字典
permission_url = '^%s$' % permission_url # 正则匹配
ret = re.search(permission_url, current_path)
if ret:
return None
return HttpResponse('Forbidden!')
# 关于list.html部分
{% extends 'stark/base.html' %}
{% block css %}
<style>
.filter_body {
padding-top: 8px;
border-top: 2px solid #a1a1a1;
padding-bottom: 12px;
border-bottom: 2px solid #a1a1a1;
}
.filter_body .active {
background-color: #3e8f3e;
color: white;
}
div {
margin-top: 2px
}
.fa:hover {
transform: scale(1.8); /*鼠标放上之后元素变成1.8倍大小*/
}
.content1:hover {
background-color: lightgrey;
}
body {
background-color: rgba(128, 128, 128, 0.11);
{#background-color:rgba(0,0,255,0.5);#}
}
</style>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<span class="pull-left" style="height: 20px; font-size: 30px;margin-top: 10px">首页</span>
<div class="panel-body panel-info">
{% if show_list.config_obj.search_fields %}
<form action="" method="get">
<div class="input-group pull-right" style="width: 400px">
<input value="{{ show_list.config_obj.search_val|default:'' }}" type="text" name="q"
class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-primary">Search!</button>
</span>
</div>
</form>
{% endif %}
</div>
<div style="margin-top: 5px;">
<div class="panel-default filter_body ">
{% for field,links in show_list.config_obj.get_list_filter_links.items %}
<div class="filter_body_item" style="margin-top: 5px">
<span class="btn btn-default btn-sm" style="width: 120px">按{{ field }}筛选</span>
{% for link in links %}
{{ link|safe }}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
<div>
<div style="margin-top: 10px" class="pull-left">
<a href="{{ add_url }}" class="btn btn-primary ">添加{{ table_name }}</a>
</div>
<form action="" method="post" class="input-group">
{% csrf_token %}
<div class="action" style="margin-top: 10px; margin-left: 10px">
<select class='form-control' name="action" id=""
style="width: 250px;display: inline-block;vertical-align: -2px;">
<option value="">--------------</option>
{% for action in show_list.config_obj.get_action_dict %}
<option value="{{ action.name }}">{{ action.desc }}</option>
{% endfor %}
</select>
<button class="btn btn-primary" style="margin-left: -4px">GO</button>
</div>
</div>
<table class="table" id="">
<thead>
<tr>
{% for item1 in show_list.get_header %}
<th>{{ item1 }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for item in show_list.get_body %}
<tr class="content1">
{% for info in item %}
<td>{{ info }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<div class="pull-right">
{{ show_list.pagination.page_html|safe }}
</div>
</form>
</div>
<script type="text/javascript">
$('input[name="checkall"]').on("click", function () {
/*全选和全不选*/
if ($(this).is(':checked')) {
$('input[name="_selected_action"]').each(function () {
$(this).prop("checked", true);
});
} else {
$('input[name="_selected_action"]').each(function () {
$(this).prop("checked", false);
});
}
});
function index() {
/*亮瞎眼的博彩闪烁*/
$('.vip_name').css('color', '#edf44f'); //默认值
setTimeout(" $('.vip_name').css('color','#fF0000')", 100); //第一次闪烁
setTimeout("$('.vip_name').css('color','#1e26cc')", 200); //第二次闪烁
}
window.setInterval(index, 400); //让index 多久循环一次
</script>
{% endblock %}
# 关于base.html部分,即list继承
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CRM</title>
<link rel="shortcut icon" href="{% static 'imgs/luffy-study-logo.png' %}">
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %} "/>
<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/>
<link rel="stylesheet" href="{% static 'css/commons.css' %} "/>
<link rel="stylesheet" href="{% static 'css/nav.css' %} "/>
<script src="/static/js/jquery-3.3.1.min.js"></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.js' %} "></script>
{% block css %}
{% endblock %}
</head>
<body>
<div class="pg-header ">
{% if not is_pop %}
<div class="nav">
<div class="logo-area left">
<a href="#">
<img class="logo" src="{% static 'imgs/logo.svg' %}">
<span style="font-size: 18px;">CRM</span>
</a>
</div>
<div class="left-menu left">
<a class="menu-item"></a>
<span>欢迎尊贵用户</span>
<span style="font-size: 40px" class="vip_name">
<!-- 固定要写load才能调用templatetags里面的方法 -->
{% load filter_tags %}
{% get_name request %}
</span>
</div>
<div class="right-menu right clearfix">
<!-- Single button -->
<div class="btn-group user-info right">
<img class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
width="50" height="50" class="img-circle" src="{% static 'imgs/default.jpg' %}">
<ul class="dropdown-menu small">
<li><a href="#" class="more-item">个人信息</a></li>
<li><a href="/logout/" class="more-item">注销</a></li>
<li><a href="/home/">修改密码</a></li>
<li><a href="/home/">更换头像</a></li>
</ul>
</div>
<a class="user-menu right">
<i class="fa fa-user" aria-hidden="true"></i>
<span>{{ request.user.name }}</span>
</a>
<a class="user-menu right">
消息
<i class="fa fa-commenting-o" aria-hidden="true"></i>
<span class="badge bg-success">2</span>
</a>
<a class="user-menu right">
通知
<i class="fa fa-envelope-o" aria-hidden="true"></i>
<span class="badge bg-success">2</span>
</a>
<a class="user-menu right">
任务
<i class="fa fa-bell-o" aria-hidden="true"></i>
<span class="badge bg-danger">4</span>
</a>
</div>
</div>
{% endif %}
</div>
<div class="pg-body">
<div class="left-menu">
{% block side_bar %}
<!-- 固定要写load才能调用templatetags里面的方法 -->
{% load filter_tags %}
{% get_menu_style request %}
{% endblock side_bar %}
</div>
<div class="right-body">
{% block content %}
{% endblock content %}
</div>
</div>
{% block js %}
{% endblock %}
</body>
</html>
# 关于用户rbac.models部分
from django.db import models
# Create your models here.
class UserInfo(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField('Role')
def __str__(self): return self.name
class Role(models.Model):
title = models.CharField(max_length=32)
permissions = models.ManyToManyField('Permission')
def __str__(self): return self.title
class Permission(models.Model):
url = models.CharField(max_length=128)
title = models.CharField(max_length=32)
# 以下为左侧多级菜单配备models,self 代表当前模型,null表示数据库可以为空,blank表示orm可以为空
type = models.CharField(max_length=32, choices=[('menu', '菜单权限'),
('menuLink', '菜单链接权限'), ('button', '按钮权限')],default='menu')
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
def __str__(self): return self.title