Web开发基础之CMDB系统开发之二
一,用户组管理模块
1,展示用户组列表
Django自带了用户表,同时也带了用户组表。他们是多对多关系。用户组模型很简单,和User模型是多对多的关系。用户组顾名思义,就是对用户进行了分组。其作用在权限控制中就是可以批量的对用户的权限许可进行分配,而不用一个一个的按用户分配,节省维护的工作量。
用户组和用户对应关系为多对多关系
查看建表语句
对应关系如下,即一个用户可以属于多个组一个组可以同时拥有多个用户
①路由
②视图
③模板
注意:注释部分找不到的函数 因为还没有, 不注释打开会报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | { % extends 'base.html' % } { % block mbx % } <div class = "row wrapper border-bottom white-bg page-heading" > <div class = "col-sm-4" > <h2>用户组展示< / h2> <ol class = "breadcrumb" > <li> <a href = "{% url 'index' %}" >首页< / a> < / li> <li> <a href = "">用户组管理< / a> < / li> <li> <a href = "">用户组展示< / a> < / li> < / ol> < / div> < / div> { % endblock % } { % block body % } <div class = "col-lg-12" > <div class = "ibox float-e-margins" > <div class = "ibox-title" > <h5>用户组展示 < / h5> < / div> <div class = "ibox-content" > { # <a class="btn btn-w-m btn-primary" href="{% url 'group_add' %}">创建用户组</a>#} <a class = "btn btn-w-m btn-primary" href = "">创建用户组< / a> <table class = "table table-striped" > <thead> <tr> <th class = "text-center" >用户组名< / th> <th class = "text-center" >组内成员< / th> <th class = "text-center" >操作< / th> < / tr> < / thead> <tbody> { % for object in object_list % } <tr> <td class = "text-center" >{{ object .name }}< / td> <td class = "text-center" > <a data - toggle = "popover" data - placement = "auto bottom" data - content = " { % for user in object .user_set. all % }{{ user.username }},{ % endfor % }"> {{ object .user_set. all .count }} < / a> < / td> <td class = "text-center" > { # <a href="{% url 'group_update' %}?gid={{ object.id }}"#} { # class="btn btn-primary btn-sm">更新</a>#} <a class = "btn btn-danger btn-sm" onclick = "group_delete({{ object.id }})" >删除< / a> < / td> < / tr> { % endfor % } < / tbody> < / table> <center> <div class = "btn-group" > { % if page_obj.has_previous % } <a href = "{% url 'group_list' %}?page={{ page_obj.previous_page_number }}" class = "btn btn-white" >上一页< / a> { % endif % } { % for page in page_range % } { % if page_obj.number = = page % } <a class = "btn btn-white active" >{{ page }}< / a> { % else % } <a class = "btn btn-white" href = "{% url 'group_list' %}?page={{ page }}" >{{ page }}< / a> { % endif % } { % endfor % } { % if page_obj.has_next % } <a href = "{% url 'group_list' %}?page={{ page_obj.next_page_number }}" class = "btn btn-white" >下一页< / a> { % endif % } < / div> < / center> < / div> < / div> < / div> { % endblock % } { % block load_js % } <script> { #function group_delete(group_id) {#} { # $.get('{% url 'group_delete' %}', {gid: group_id}, function (res) {#} { # if (res.status == 0) {#} { # swal({#} { # title: res.msg,#} { # type: 'success',#} { # confirmButtonText: "确定"#} { # }, function () {#} { # window.location.reload()#} { # });#} { # } else {#} { # swal({#} { # title: res.msg,#} { # type: 'error',#} { # confirmButtonText: "确定"#} { # });#} { # }#} { # });#} { #};#} < / script> { % endblock % } |
在数据库插入一个用户组并且在该用户组插入两个用户
1 | insert into auth_group values(null, '管理员组' ); |
在管理员放入两个用户
1 2 3 | # (null,1,1)分别代表自增 用户ID 用户组ID insert into auth_user_groups values(null, 1 , 1 ); insert into auth_user_groups values(null, 20 , 1 ); |
页面查看
注意:这里使用了插件点击组内成员会显示该用户组内的成员账号信息
需要之前用户列表路由加了符号^否则用户组列表会展示用户列表内容
代码位置
2,创建用户组
修改base.html把用户组管理链接添加进去
①路由
②视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class GroupAddView(ListView): template_name = 'group_add.html' model = User def post( self , request): data = request.POST print (data) res = { 'status' : 0 , 'msg' : '添加成功' } try : group = Group() # 用户组名称 group.name = data.get( 'name' ) # 存储组 要不后面找不到组ID group.save() # 此用户组添加的用户 for i in data.getlist( 'group_user' ): # 通过组对象反向到user对象 添加多对多的关系 group.user_set.add(User.objects.get( id = i)) except Exception as e: print (e) res = { 'status' : 1 , 'msg' : '添加失败' } return JsonResponse(res) |
③模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | { % extends 'base.html' % } { % block load_css % } <link href = "/static/css/plugins/sweetalert/sweetalert.css" rel = "stylesheet" > <link href = "/static/css/plugins/select2/select2.min.css" rel = "stylesheet" > { % endblock % } { % block mbx % } <div class = "row wrapper border-bottom white-bg page-heading" > <div class = "col-sm-4" > <h2>创建用户组< / h2> <ol class = "breadcrumb" > <li> <a href = "{% url 'index' %}" >首页< / a> < / li> <li> <a href = "">用户组管理< / a> < / li> <li> <a href = "">创建用户组< / a> < / li> < / ol> < / div> < / div> { % endblock % } { % block body % } <div class = "ibox-content" > <form id = "submit_form" class = "form-horizontal" > { % csrf_token % } <div class = "form-group" ><label class = "col-sm-2 control-label" >用户组名< / label> <div class = "col-sm-6" >< input type = "text" class = "form-control" name = "name" >< / div> < / div> <div class = "hr-line-dashed" >< / div> <div class = "form-group" ><label class = "col-sm-2 control-label" >选择用户< / label> <div class = "col-sm-6" > <select class = "select2_demo_2 form-control" multiple = "multiple" name = "group_user" > { % for user in object_list % } <option value = "{{ user.id }}" >{{ user.username }}< / option> { % endfor % } < / select> < / div> < / div> <div class = "hr-line-dashed" >< / div> <div class = "form-group" > <div class = "col-sm-4 col-sm-offset-2" > <button class = "btn btn-white" type = "submit" >取消< / button> <button class = "btn btn-primary" type = "submit" >保存更改< / button> < / div> < / div> < / form> < / div> { % endblock % } { % block load_js % } <script src = "/static/js/plugins/validate/jquery.validate.js" >< / script> <script src = "/static/js/plugins/validate/messages_zh.js" >< / script> <script src = "/static/js/plugins/sweetalert/sweetalert.min.js" >< / script> <! - - Select2 - - > <script src = "/static/js/plugins/select2/select2.full.min.js" >< / script> <script> $( ".select2_demo_2" ).select2(); $(document).ready(function () { $( "#submit_form" ).validate({ rules: { name: { required: true } }, submitHandler: function () { var str = $( '#submit_form' ).serialize(); $.post( '{% url ' group_add ' %}' , str , function (res) { if (res.status = = 0 ) { swal({ title: res.msg, type : 'success' , confirmButtonText: "确定" }, function () { window.location.href = '{% url ' group_list ' %}' ; }); } else { swal({ title: res.msg, type : 'error' , confirmButtonText: "确定" }); } }); } }); }); < / script> { % endblock % } |
修改用户组模板设置创建用户组链接
页面创建
3,更新用户组
更新用户组合更新用户类似,需要额外处理的是,回显用户列表,需要判断用户是否在用户组,如果在处理为下拉框选中状态。
①路由
②视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | class GroupUpdateView(ListView): template_name = 'group_update.html' model = User def get_context_data( self , * * kwargs): context = super (GroupUpdateView, self ).get_context_data( * * kwargs) context[ 'group_obj' ] = Group.objects.get( id = self .request.GET.get( 'id' )) return context def post( self , request): data = request.POST print (data) res = { 'status' : 0 , 'msg' : '更新成功' } try : group = Group.objects.get( id = data.get( 'id' )) # 用户组名称 group.name = data.get( 'name' ) # 存储组 要不后面找不到组ID group.save() # 清空组和用户的关系 group.user_set.clear() # 此用户组添加的用户 for i in data.getlist( 'group_user' ): # 通过组对象反向到user对象 添加多对多的关系 group.user_set.add(User.objects.get( id = i)) except Exception as e: print (e) res = { 'status' : 1 , 'msg' : '更新失败' } return JsonResponse(res) |
③模板
组列表设置按钮链接
更新模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | { % extends 'base.html' % } { % block load_css % } <link href = "/static/css/plugins/select2/select2.min.css" rel = "stylesheet" > <link href = "/static/css/plugins/sweetalert/sweetalert.css" rel = "stylesheet" > { % endblock % } { % block mbx % } <div class = "row wrapper border-bottom white-bg page-heading" > <div class = "col-sm-4" > <h2>更新用户组< / h2> <ol class = "breadcrumb" > <li> <a href = "{% url 'index' %}" >首页< / a> < / li> <li> <a href = "">用户组管理< / a> < / li> <li> <a href = "">更新用户组< / a> < / li> < / ol> < / div> < / div> { % endblock % } { % block body % } <div class = "ibox-content" > <form id = "submit_form" class = "form-horizontal" > { % csrf_token % } <div class = "form-group" ><label class = "col-sm-2 control-label" >用户组名< / label> <div class = "col-sm-6" >< input type = "text" class = "form-control" name = "name" value = "{{ group_obj.name }}" > < / div> < / div> <div class = "hr-line-dashed" >< / div> <div class = "form-group" ><label class = "col-sm-2 control-label" >选择用户< / label> <div class = "col-sm-6" > <select class = "select2_demo_2 form-control" multiple = "multiple" name = "group_user" > { % for user in user_list % } <option { % if user in group_obj.user_set. all % }selected{ % endif % } value = "{{ user.id }}" >{{ user.username }} < / option> { % endfor % } < / select> < / div> < / div> <div class = "hr-line-dashed" >< / div> <div class = "form-group" > <div class = "col-sm-4 col-sm-offset-2" > < input value = "{{ group_obj.id }}" type = "hidden" name = "id" > <a class = "btn btn-white" href = "{% url 'group_list' %}" >返回< / a> <button class = "btn btn-primary" type = "submit" >保存更改< / button> < / div> < / div> < / form> < / div> { % endblock % } { % block load_js % } <script src = "/static/js/plugins/validate/jquery.validate.js" >< / script> <script src = "/static/js/plugins/validate/messages_zh.js" >< / script> <script src = "/static/js/plugins/sweetalert/sweetalert.min.js" >< / script> <! - - Select2 - - > <script src = "/static/js/plugins/select2/select2.full.min.js" >< / script> <script> $( ".select2_demo_2" ).select2(); $(document).ready(function () { $( "#submit_form" ).validate({ rules: { name: { required: true } }, submitHandler: function () { var str = $( '#submit_form' ).serialize(); $.post( '{% url ' group_update ' %}' , str , function (res) { if (res.status = = 0 ) { swal({ title: res.msg, type : 'success' , confirmButtonText: "OK" }, function () { window.location.href = '{% url ' group_list ' %}' ; }); } else { swal({ title: res.msg, type : 'error' , confirmButtonText: "知道了" }); } }); } }); }); < / script> { % endblock % } |
页面显示
4,删除用户组
①路由
②视图
1 2 3 4 5 6 7 8 9 10 11 12 13 | class GroupDeleteView(View): def get( self , request): gid = request.GET.get( 'gid' ) res = { 'status' : 0 , 'msg' : '删除成功' } try : Group.objects.get( id = gid).delete() print (Group.DoesNotExist) except Group.DoesNotExist: res = { 'status' : 1 , 'msg' : '用户组不存在,删除失败' } except Exception as e: print (e) res = { 'status' : 1 , 'msg' : '未知错误,删除失败' } return JsonResponse(res) |
③模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <script> function group_delete(group_id) { if (confirm( '确认删除吗?' )) { $.get( '{% url ' group_delete ' %}' , {gid: group_id}, function (res) { if (res.status = = 0 ) { swal({ title: res.msg, type : 'success' , confirmButtonText: "确定" }, function () { window.location. reload () }); } else { swal({ title: res.msg, type : 'error' , confirmButtonText: "确定" }); } }); }; } < / script> |
页面显示
二,权限管理模块
1,Django权限介绍
Django的框架提供了模型级的权限控制, 即可以检查用户是否对某个数据表拥有增(add), 改(change), 删(delete)权限。Django默认权限模型
1 | from django.contrib.auth.models import Permission |
Django的权限表和用户是多对多关系,同时跟用户组也是多对多关系。
也就代表一个用户可以有自己的权限同时也可以有所属组的权限。
这是Django的权限表,里面有一个content_type_id关联的就是django_content_type表,所以而django_content_type表中关联了APP和模型。所以这是模型级别的权限控制。
举个例子,我们可以控制某个用户是否具有查看用户列表或者创建用户列表的权限。而无法判断某个用户对某条数据是不是有权限。
当然我们也可以后期自己去扩展数据权限,但是我们这个系统控制在模型权限就足够了。
关联关系
2,展示权限列表
①路由
②视图
③模板
基础模板base.html增加链接
页面查看
重写get_queryset过滤系统默认的英文显示
1 2 3 4 5 6 7 8 | class PermListView(ListView): template_name = 'perm_list.html' model = Permission paginate_by = 7 def get_queryset( self ): queryset = super (PermListView, self ).get_queryset() queryset = queryset.exclude(name__regex = '[a-zA-Z]' ) return queryset |
编写模板增加中文显示元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Profile(models.Model): name_cn = models.CharField(max_length = 50 , verbose_name = '中文名称' ) wechat = models.CharField(max_length = 50 , verbose_name = '中文名称' ) phone = models.CharField(max_length = 11 , verbose_name = '电话' ) info = models.TextField(verbose_name = '备注' ) profile = models.OneToOneField(User) class Meta: # 清空权限 default_permissions = [] # 重新定义 permissions = ( ( 'user_add' , '添加用户' ), ( 'user_show' , '查看用户' ), ( 'user_update' , '修改用户' ), ( 'user_delete' , '删除用户' ) ) |
迁移数据
查看数据表
页面显示
3,用户权限设置功能
①路由
②视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | class UserSetPermView(ListView): template_name = 'user_set_perm.html' model = Permission paginate_by = 7 def get_context_data( self , * * kwargs): context = super (UserSetPermView, self ).get_context_data( * * kwargs) context[ 'user_obj' ] = User.objects.get( id = self .request.GET.get( 'id' )) return context def get_queryset( self ): queryset = super (UserSetPermView, self ).get_queryset() queryset = queryset.exclude(name__regex = '[a-zA-Z]' ) return queryset def post( self , request): data = request.POST print (data) res = { 'status' : 0 , 'msg' : '设置成功' } try : # 获取到用户对象 user = User.objects.get( id = data.get( 'uid' )) # 添加权限关系 user.user_permissions = data.getlist( 'perm_list[]' ) user.save() except Exception as e: print (e) res = { 'status' : 1 , 'msg' : '设置失败' } return JsonResponse(res) |
③模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | { % extends 'base.html' % } { % block load_css % } <link href = "/static/css/plugins/sweetalert/sweetalert.css" rel = "stylesheet" > <link href = "/static/css/plugins/select2/select2.min.css" rel = "stylesheet" > { % endblock % } { % block body % } <div class = "row" > <div class = "col-lg-12" > <div class = "ibox" > <div class = "ibox-title" > <h5>用户权限选择< / h5> < / div> <div><h1>用户{{ user_obj }}< / h1>< / div> <div class = "ibox-content" > <form id = "form" action = "#" class = "wizard-big" > <select class = "form-control dual_select" multiple id = "perm_form" > { % for perm_obj in object_list % } <option { % if perm_obj in user_obj.user_permissions. all % }selected{ % endif % } value = "{{ perm_obj.id }}" >{{ perm_obj.name }}< / option> { % endfor % } < / select> < / form> <div class = "modal-footer" > <button type = "button" class = "btn btn-white" onclick = "history.back()" >返回 < / button> <button type = "button" class = "btn btn-primary" onclick = "submit_user_perm({{ user_obj.id }})" >保存更改 < / button> < / div> < / div> < / div> < / div> < / div> { % endblock % } { % block load_js % } <script src = "/static/js/plugins/validate/jquery.validate.js" >< / script> <script src = "/static/js/plugins/validate/messages_zh.js" >< / script> <script src = "/static/js/plugins/sweetalert/sweetalert.min.js" >< / script> <! - - Dual Listbox - - > <script src = "/static/js/plugins/dualListbox/jquery.bootstrap-duallistbox.js" >< / script> <script> $( '.dual_select' ).bootstrapDualListbox({ selectorMinimalHeight: 160 }); function submit_user_perm(user_id) { var data = {}; data[ 'perm_list' ] = $( '#perm_form' ).val(); data[ 'uid' ] = user_id; data[ 'csrfmiddlewaretoken' ] = "{{ csrf_token }}" ; $.post( '{% url ' user_set_perm ' %}' , data, function (res) { if (res.status = = 0 ) { swal({ title: res.msg, type : 'success' , confirmButtonText: "OK" }, function () { window.location.href = '{% url ' user_list ' %}' ; }); } else { swal({ title: res.msg, type : 'error' , confirmButtonText: "知道了" }); } }) } < / script> { % endblock % } |
·页面显示
设置完查看MySQL数据库
4,用户组权限设置
与用户权限设置类似
5,权限使用
权限限制功能
①前端限制 页面中不显示功能入口
缺点:可以直接通过url访问
②后端限制 查询数据库是否具有权限
使用导入模块
1 2 | from django.utils.decorators import method_decorator from django.contrib.auth.decorators import login_required, permission_required |
1 2 3 4 5 | @method_decorator (login_required()) @method_decorator (permission_required( 'user.user_add' )) def get( self , request): context = super (UserAddView, self ).get_context_data() return context |
没有权限的用户会跳到登录页面
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2018-12-21 Docker Macvlan网络部署
2018-12-21 Docker多主机网络
2018-12-21 Docker Compose一键部署Nginx反向代理Tomcat集群
2017-12-21 Python全栈day10(基本数据类型及其常用方法)
2017-12-21 Python全栈day10(运算符)
2017-12-21 Rsync文件同步机备份工具使用