CRM——权限
一、引入权限组件
1、引入权限组件rbac
拷贝之前写好的rbac应用到CRM_demo项目下。
在settings中注册rbac的app:
1 2 3 4 5 6 7 8 9 10 11 | INSTALLED_APPS = [ 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'crm.apps.CrmConfig' , 'stark.apps.StarkConfig' , 'rbac.apps.RbacConfig' ] |
settings中添加rabc中间件:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'rbac.serive.rbac.ValidPermission' ]
2、员工表Userinfo与rbac.User表做一对一关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from rbac.models import * class UserInfo(models.Model): """ 员工表 """ name = models.CharField(verbose_name = '员工姓名' , max_length = 16 ) username = models.CharField(verbose_name = '用户名' , max_length = 32 ) password = models.CharField(verbose_name = '密码' , max_length = 64 ) email = models.EmailField(verbose_name = '邮箱' , max_length = 64 ) # 模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。 depart = models.ForeignKey(verbose_name = '部门' , to = "Department" , to_field = "code" , on_delete = models.CASCADE) user = models.OneToOneField(to = User, null = True , on_delete = models.CASCADE) def __str__( self ): return self .name |
由于是临时添加的字段,因此添加参数null=True。
然后完成数据迁移:
1 2 | manage.py@CRM_demo > makemigrations manage.py@CRM_demo > migrate |
二、给权限控制配置注册stark
1、rbac/stark.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from stark.service.stark import site,ModelStark from .models import * class UserConfig(ModelStark): list_display = [ "name" , "roles" ] site.register(User, UserConfig) class RoleConfig(ModelStark): list_display = [ "title" , "permissions" ] site.register(Role, RoleConfig) class PermissionConfig(ModelStark): list_display = [ "id" , "title" , "url" , "group" , "action" ] site.register(Permission, PermissionConfig) site.register(PermissionGroup) |
2、添加权限组
3、添加权限
注意:
(1)输入url字段过长
原来在models.py中配置url的max_length=32这个长度不够输入全部路径,因此将其改为max_length=64。
(2)编辑操作的url和action
编辑操作的url取的是crm应用的路径在这里是change,但action取的是rbac的操作分类是edit。

{% extends 'base.html' %} {% block con %} <h4>角色列表</h4> {% if per.add %} <a href="/roles/add" class="btn btn-primary">添加角色</a> {% endif %} <table class="table table-bordered table-striped"> <tbody> {% for role in role_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ role.title }}</td> <td> {% if per.delete %} <a href="/roles/delete/{{ user.pk }}" class="btn btn-danger">删除</a> {% endif %} {% if per.edit %} <a href="/roles/edit/{{ user.pk }}" class="btn btn-warning">编辑</a> {% endif %} </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
(3)查看学生成绩添加
这个是点击学生表对应查看的,不能放在菜单栏中,因此不能将action设为list.
4、添加角色
5、添加用户
6、给员工分配对应的user
给每个员工分配对应的user:
三、登录、引入中间件
1、crm_demo/urls.py配置登录url
1 2 3 4 5 6 7 8 9 10 11 | from django.contrib import admin from django.urls import path from django.conf.urls import url from stark.service.stark import site from crm import views urlpatterns = [ path( 'admin/' , admin.site.urls), url(r '^stark/' , site.urls), url(r '^login/' , views.login) ] |
2、crm/view.py视图配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from django.shortcuts import render, HttpResponse # Create your views here. from rbac.models import User from rbac.service.permissions import initial_session def login(request): if request.method = = 'POST' : user = request.POST.get( "user" ) pwd = request.POST.get( "pwd" ) user = User.objects. filter (name = user, pwd = pwd).first() if user: # 登录成功 request.session[ "user_id" ] = user.pk # 注册权限到session中 initial_session(user, request) return HttpResponse( "登录成功" ) return render(request, "login.html" , locals ()) |
3、引入中间件
1 2 3 4 5 6 7 8 9 10 | MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware' , 'django.contrib.sessions.middleware.SessionMiddleware' , 'django.middleware.common.CommonMiddleware' , 'django.middleware.csrf.CsrfViewMiddleware' , 'django.contrib.auth.middleware.AuthenticationMiddleware' , 'django.contrib.messages.middleware.MessageMiddleware' , 'django.middleware.clickjacking.XFrameOptionsMiddleware' , 'rbac.service.rbac.ValidPermission' ] |
至此权限控制已经实现了,当不同用户登录时,只能访问具有权限的页面。
四、页面调整
1、拷贝base.html及调整
将rbac应用下的base.html拷贝到CRM_demo项目下的templates里,在这里base.html是首先调用的,可以在不修改rbac组件的情况下调整base.html。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 引入 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css"> <script src="/static/js/jquery-1.12.4.min.js"></script> <link rel="stylesheet" href="/static/css/add.css"> <link rel="stylesheet" href="/static/css/list.css"> <style> .header { width: 100%; height: 60px; background-color: #336699; } .menu { background-color: bisque; position: fixed; top: 60px; bottom: 0px; left: 0px; width: 200px; } .content { position: fixed; top: 60px; bottom: 0; right: 0; left: 200px; overflow: auto; /* 滚动条 */ } .menu_btn { font-size: 18px; text-align: center; padding: 30px 0; } </style> </head> <body> <div class="header"> <p>{{ user.name }}</p> </div> <div class="contain"> {% load my_tags %} <div class="menu"> {% get_menu request %} </div> <div class="content"> {% block con %} {% endblock %} </div> </div> </body> </html>
被引入base.html的两个css文件分别是/stark/add_view.html和/stark/list_view.html的css样式。

input, select { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } .error { color: red; }

.filter a { text-decoration: none; /* 取消a标签颜色 */ color: grey; } .active { color: red !important; /* 提升优先级 */ }
2、模板继承
此处修改的是stark子应用里的模板。
(1)add_view.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | {% extends 'base.html' %} {% block con %} < h3 >添加页面</ h3 > {% include 'form.html' %} < script > function pop(url) { window.open(url, "", "width=600, height=400, top=100, left=100") } function pop_response(pk, text, id) { console.log(pk, text, id); // 10 人民邮电出版社 id_publish console.log(typeof text); // string // 选择哪一个select标签 // option文本值和value值 var $option = $('< option >'); // 创建标签:< option ></ option > $option.html(text); // 给标签添加文本:< option >南京出版社</ option > $option.val(pk); // 给标签添加value:< option value=111>南京出版社</ option > $option.attr("selected", "selected"); // 添加属性selected:< option value="111" selected="selected">南京出版社</ option > $("#" + id).append($option); // 将标签添加到id="id_publish"的标签中 } </ script > {% endblock %} |
(2)change_view.html
1 2 3 4 5 6 | {% extends 'base.html' %} {% block con %} < h3 >编辑页面</ h3 > {% include 'form.html' %} {% endblock %} |
(3)list_view.html

{% extends 'base.html' %} {% block con %} <h4>数据列表</h4> <div class="container"> <div class="row"> <div class="col-md-9"> {# <a href="add/" class="btn btn-primary">添加数据</a> #} <a href="{{ add_url }}" class="btn btn-primary">添加数据</a> {% if show_list.config.search_fields %} <form action="" class="pull-right"> <input type="text" name="q" value="{{ show_list.config.key_word }}"> <button>搜索</button> </form> {% endif %} <form action="" method="post"> {% csrf_token %} <select name="action" id="" style="width: 200px; padding: 5px 8px; display: inline-block"> <option value="">-----------</option> {% for item in show_list.get_action_list %} <option value="{{ item.name }}">{{ item.desc }}</option> {% endfor %} </select> <button type="submit" class="btn-info">Go</button> <table class="table table-bordered table-striped"> <thead> <tr> {% for item in header_list %} <th>{{ item }}</th> {% endfor %} </tr> </thead> <tbody> {% for data in new_data_list %} <tr> {% for item in data %} <td>{{ item }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> <nav> <ul class="pagination"> {{ show_list.pagination.page_html|safe }} </ul> </nav> </form> </div> {% if showlist.config.list_filter %} {# list_filter有值才显示FILTER #} <div class="filter"> <h4>Filter</h4> {% for filter_field, linktags in show_list.get_filter_linktags.items %} <div class="well"> {# upper方法改为大写 #} <p>{{ filter_field.upper }}</p> {% for link in linktags %} <p>{{ link|safe }}</p> {% endfor %} </div> {% endfor %} </div> {% endif %} </div> </div> <script> // 复选框全选 $("#choice").click(function () { if ($(this).prop("checked")) { // 如果是选中状态 $(".choice_item").prop("checked", true); } else { $(".choice_item").prop("checked", false) } }) </script> {% endblock %}
(4)public.html
在CRM_demo项目下的templates里创建。

{% extends 'base.html' %} {% block con %} <h3>公共客户</h3> <div class="container"> <div class="row"> <div class="col-md-6"> <table class="table table-bordered table-striped"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>QQ</th> <th>课程顾问</th> <th>跟进详情</th> <th>确认跟进</th> </tr> </thead> <tbody> {% for customer in customer_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ customer.name }}</td> <td>{{ customer.qq }}</td> <td>{{ customer.consultant }}</td> <td><a href="/stark/crm/consultrecord/?customer={{ customer.pk }}">跟进记录</a></td> <td><a href="/stark/crm/customer/further/{{ customer.pk }}">确认跟进</a></td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> {% endblock %}
3、登录后显示效果
侧边菜单都是显示的组的名字:客户管理。
4、修改显示权限名称
修改/rbac/service/permissions.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def initial_session(user, request): """注册权限到session中""" # 注册菜单权限 # permissions = user.roles.all().values("permissions__url", "permissions__group_id", "permissions__action","permissions__group__title").distinct() # 在这里将权限组名改为权限名 permissions = user.roles. all ().values( "permissions__url" , "permissions__group_id" , "permissions__action" , "permissions__title" ).distinct() print ( "permissions" , permissions) menu_permission_list = [] # 菜单栏中权限列表:空列表 for item in permissions: # item是里面的字典 if item[ "permissions__action" ] = = "list" : # 列表里面套一个个的元组,每个元组包含url和权限组title # menu_permission_list.append((item["permissions__url"], item["permissions__group__title"])) # 改为权限名 menu_permission_list.append((item[ "permissions__url" ], item[ "permissions__title" ])) |
登录查看页面:
5、rbac登录问题
测试中发现一个问题,当想调整权限和角色等信息时,登录/stark/rbac/permission等页面,所有账户都没有访问权限。
这里必须通过admin组件,添加系统管理员用户和用户组,添加访问、编辑、删除rbac相关页面的权限。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术