权限组件(11):基于formset实现批量增加
效果图:
增加页面:
编辑页面:

因为后面要对权限进行批量操作,所以先用这个示例演示下如何实现批量操作
数据库
from django.db import models class Menu(models.Model):
"""
菜单表
"""
title = models.CharField(verbose_name='菜单名称', max_length=32)
icon = models.CharField(verbose_name='图标', max_length=32) def __str__(self):
return self.title class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题', max_length=32)
url = models.CharField(verbose_name='含正则的URL', max_length=128) name = models.CharField(verbose_name='URL的别名', max_length=32, unique=True) menu = models.ForeignKey(verbose_name='所属菜单', to='Menu', null=True, blank=True,
help_text='null表示不是菜单;非null表示是二级菜单', on_delete=models.CASCADE) pid = models.ForeignKey(verbose_name='关联的权限', to='Permission', null=True, blank=True, related_name='parents',
help_text='对于非菜单权限需要选择一个可以成为菜单的权限,用于做默认展开和选中菜单',
on_delete=models.CASCADE) def __str__(self):
return self.title
一、配置路由
from django.urls import path
from formset import views urlpatterns = [
path('multi/add', views.multi_add),
path('multi/edit', views.multi_edit),
]
二、forms表单验证
from django import forms from formset import models class MultiPermissionForm(forms.Form):
title = forms.CharField()
url = forms.CharField()
name = forms.CharField()
menu_id = forms.ChoiceField(
choices=[(None, '----------')],
required=False
)
pid_id = forms.ChoiceField(
choices=[(None, '----------')],
required=False
) def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
menu__isnull=True).values_list('id', 'title') class MultiUpdatePermissionForm(forms.Form):
id = forms.IntegerField(
widget=forms.HiddenInput()
)
title = forms.CharField()
url = forms.CharField()
name = forms.CharField()
menu_id = forms.ChoiceField(
choices=[(None, '----------')],
required=False
)
pid_id = forms.ChoiceField(
choices=[(None, '----------')],
required=False
) def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
menu__isnull=True).values_list('id', 'title')
三、视图函数
from django.forms import formset_factory
from django.shortcuts import render, HttpResponse from formset import models
from formset.forms.formset import MultiPermissionForm, MultiUpdatePermissionForm def multi_add(request):
"""
批量增加
:param request:
:return:
""" formset_class = formset_factory(MultiPermissionForm, extra=5) # 在内部生成五个form表单 if request.method == 'GET':
formset = formset_class()
return render(request, 'multi_add.html', {'formset': formset}) formset = formset_class(data=request.POST) # 储存的所有信息,包括html标签
if formset.is_valid():
no_repeat_field = True # 要把cleaned_data放到for循环上面,因为在下面一旦cleaned_data检测到错误信息就会报错。里面储存了一个个form[{},{},{}......]
form_list = formset.cleaned_data # 检查formset中有没有错误信息,没有则将用户提交的数据取到。有错误信息就报错
for num in range(0, formset.total_form_count()):
form = form_list[num] # 一个具体的form
if not form:
continue
try:
# 下面的方式和model.Permission.object.create(**row)效果一样,这里用这种方式是为了捕获唯一性错误
permission_obj = models.Permission(**form)
permission_obj.validate_unique() # 检查当前对象在数据库是否存在唯一的
permission_obj.save()
except Exception as e:
formset.errors[num].update(e) # 把错误信息放到对应的form里面
no_repeat_field = False if no_repeat_field:
return HttpResponse('提交成功')
else:
return render(request, 'multi_add.html', {'formset': formset})
return render(request, 'multi_add.html', {'formset': formset}) def multi_edit(request):
formset_class = formset_factory(MultiUpdatePermissionForm, extra=0) # 默认等于1,如果不想让它多增加一个,就把默认改成0
if request.method == 'GET':
formset = formset_class(
initial=models.Permission.objects.all().values('id', 'title', 'name', 'url', 'menu_id', 'pid_id')
)
return render(request, 'multi_edit.html', {'formset': formset}) formset = formset_class(data=request.POST)
if formset.is_valid():
no_repeat_field = True
form_list = formset.cleaned_data
for num in range(0, formset.total_form_count()):
form = form_list[num]
if not form:
continue
permission_id = form.pop('id')
try:
permission_obj = models.Permission.objects.filter(id=permission_id).first()
for key, value in form.items():
setattr(permission_obj, key, value) # 更新数据库的字段
permission_obj.validate_unique()
permission_obj.save()
except Exception as e:
formset.errors[num].update(e)
no_repeat_field = False
if no_repeat_field:
return HttpResponse("提交成功")
else:
return render(request, 'multi_edit.html', {'formset': formset})
return render(request, 'multi_edit.html', {'formset': formset})
四、模板渲染
multi_add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css">
</head>
<body> <div class="container" style="margin-top: 100px">
<div class="row">
<form action="" method="post" novalidate>
{% csrf_token %}
{{ formset.management_form }}
<table class="table table-hover table-stripped" border="1">
<thead>
<tr>
<th>标题</th>
<th>URL</th>
<th>Name</th>
<th>菜单</th>
<th>父权限</th>
</tr>
</thead>
<tbody>
{% for form in formset %}
<tr>
{% for field in form %}
<td>
{{ field }}
<span style="color:red">{{ field.errors.0 }}</span>
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<hr/>
<input type="submit" value="提交" class="btn btn-primary">
</form>
</div>
</div> </body>
</html>
multi_edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css">
</head>
<body> <div class="container" style="margin-top: 100px">
<div class="row">
<form action="" method="post" novalidate>
{% csrf_token %}
{{ formset.management_form }}
<table class="table table-hover table-stripped" border="1">
<thead>
<tr>
<th>标题</th>
<th>URL</th>
<th>Name</th>
<th>菜单</th>
<th>父权限</th>
</tr>
</thead>
<tbody>
{% for form in formset %}
<tr>
{% for field in form %}
{% if forloop.first %}
{{ field }}
{% else %}
<td>
{{ field }}
<span style="color:red">{{ field.errors.0 }}</span>
</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<hr/>
<input type="submit" value="提交" class="btn btn-primary">
</form>
</div>
</div> </body>
</html>
edit和add的区别是edit多了个id并把id隐藏起来了
权限组件(11):基于formset实现批量增加的更多相关文章
- rbac 权限分配, 基于formset实现,批量增加
这里需要两个知识点: - formset - 自动发现项目中的URL1. 什么是formset: Django中 form组件 或 ModelForm组件,用于做一个表单的验证. 接收前端form表单 ...
- rbac 权限分配, 基于formset实现,批量编辑
已经完成了 批量添加的功能. 还想要一个批量修改的功能了.随之而来的第一个问题就是, 我们的formset 并不是一条记录.而是 多条记录,甚至整个表的记录.那么显而易见的问题就是,当前端页面把数 ...
- CRM第一篇:权限组件之权限控制
一.权限组件(1):一级菜单 二.权限组件(2):二级菜单 三.权限组件(3):默认选中非菜单(二级菜单) 四.权限组件(4):给动态菜单增加面包屑导航 五.权限组件(5):权限粒度控制到按钮 六.权 ...
- Web端权限管理新增实用功能:批量增加操作,简单方便快速!
扩展了吉日嘎拉的Web端权限管理功能后,每次添加菜单倒没啥问题,毕竟菜单的数量有限,可是每增加一个模块.功能或者说权限控制点,就得针对各种常规操作,新增很多遍. 浪费时间,还容易出错.新增了一个字典表 ...
- CRM【第一篇】: 权限组件之权限控制
1. 问:为什么程序需要权限控制? 答:生活中的权限限制,① 看灾难片电影<2012>中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临:② 屌丝们,有没有想过为什么那些长得漂亮身 ...
- Django-CRM项目学习(七)-权限组件的设置以及权限组件的应用
开始今日份整理 1.利用自定制标签,增加展示权限,权限分级设定 1.1 在权限组件中创建自定义标签 使用自定义标签的目的,使各个数据进行分离 1.2 导入自定义标签包 自定义标签复习(自定义标签有三种 ...
- python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)
一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...
- rbac权限组件整合到实际项目的全过程详述
rbac简介 项目的GitHub地址 欢迎Download&Fork&Star:https://github.com/Wanghongw/CombineRbac 另外,本文只简单介绍一 ...
- day 71 crm(8) 权限组件的设置,以及权限组件的应用
---恢复内容开始--- 前情提要: strak 组件是增删改查组件 , 生活中,需求权限组件, 不足: 1,前后端不分离, 2, 空url也会刷新界面,造成资源浪费 3,如果角色忘记设置权 ...
随机推荐
- HTTPS和SSL证书
1. HTTPS工作原理 HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,(目的是安全的获得对称密钥用户后续传输加密)过程的简单描述如下: a).浏览器讲自己支持的多个加 ...
- linux笔记学习大全,包括相关软件
1.如果tomcat正常启动,内部浏览器可以访问,外部电脑的浏览器布恩那个访问? 可以使用如下命令: iptables -F firewall-cmd --add-port=8080/tcp --pe ...
- java 核心技术 读后总结
总结 1.少用八进制,以及二进制. 那么就是直接用16进制或10进制吗?额,想当年有这样搞过,后面就uuid了. 2.>>>用0填充高位>>用符号位填充高位<< ...
- webpack.config.js====配置babel
参考:https://www.jianshu.com/p/9808f550c6a91. 安装依赖babel-loader: 负责 es6 语法转化babel-preset-env: 包含 es6.7 ...
- window.open()方法详解
, 最基本的弹出窗口代码 window.open('page.html'); 2, 经过设置后的弹出窗口 window.open('page.html', 'newwindow', 'heig ...
- 十分钟玩转 jQuery、实例大全(参考自博主索宁)
十分钟玩转 jQuery.实例大全(参考自博主索宁) 一.简介 书写规则 支持链式操作: 在变量前加"$"符号(var $variable = jQuery 对象): 注:此规定并 ...
- 零基础逆向工程27_Win32_01_宽字符_MessageBox_win32调试输出
1 多字节字符 ASCII码表:0 ~ 2^7-1 扩展ASCII码表:2^7 ~ 2^8-1 什么是GB2312:1980年,两个字节存储一个汉字:不通用,别国会有乱码. UCICODE:只有一个字 ...
- meterpreter > sysinfo
meterpreter > sysinfoComputer : test-VCS86VROS : Windows XP (Build 2600).Architecture : x86System ...
- 标准对象 -------JavaScript
本文摘要:http://www.liaoxuefeng.com/ 在JavaScript的世界里,一切都是对象. 但是某些对象还是和其他对象不太一样.为了区分对象的类型,我们用typeof操作符获取对 ...
- C# 运用StreamReader类和StreamWriter类实现文件的读写操作
对文件的读写操作应该是最重要的文件操作,System.IO命名空间为我们提供了诸多文件读写操作类,在这里我要向大家介绍最常用也是最基本的StreamReader类和StreamWriter类.从这两个 ...