效果图:

增加页面:

编辑页面:

因为后面要对权限进行批量操作,所以先用这个示例演示下如何实现批量操作

数据库

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实现批量增加的更多相关文章

  1. rbac 权限分配, 基于formset实现,批量增加

    这里需要两个知识点: - formset - 自动发现项目中的URL1. 什么是formset: Django中 form组件 或 ModelForm组件,用于做一个表单的验证. 接收前端form表单 ...

  2. rbac 权限分配, 基于formset实现,批量编辑

    已经完成了  批量添加的功能. 还想要一个批量修改的功能了.随之而来的第一个问题就是,  我们的formset 并不是一条记录.而是 多条记录,甚至整个表的记录.那么显而易见的问题就是,当前端页面把数 ...

  3. CRM第一篇:权限组件之权限控制

    一.权限组件(1):一级菜单 二.权限组件(2):二级菜单 三.权限组件(3):默认选中非菜单(二级菜单) 四.权限组件(4):给动态菜单增加面包屑导航 五.权限组件(5):权限粒度控制到按钮 六.权 ...

  4. Web端权限管理新增实用功能:批量增加操作,简单方便快速!

    扩展了吉日嘎拉的Web端权限管理功能后,每次添加菜单倒没啥问题,毕竟菜单的数量有限,可是每增加一个模块.功能或者说权限控制点,就得针对各种常规操作,新增很多遍. 浪费时间,还容易出错.新增了一个字典表 ...

  5. CRM【第一篇】: 权限组件之权限控制

    1. 问:为什么程序需要权限控制? 答:生活中的权限限制,① 看灾难片电影<2012>中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临:② 屌丝们,有没有想过为什么那些长得漂亮身 ...

  6. Django-CRM项目学习(七)-权限组件的设置以及权限组件的应用

    开始今日份整理 1.利用自定制标签,增加展示权限,权限分级设定 1.1 在权限组件中创建自定义标签 使用自定义标签的目的,使各个数据进行分离 1.2 导入自定义标签包 自定义标签复习(自定义标签有三种 ...

  7. python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)

    一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...

  8. rbac权限组件整合到实际项目的全过程详述

    rbac简介 项目的GitHub地址 欢迎Download&Fork&Star:https://github.com/Wanghongw/CombineRbac 另外,本文只简单介绍一 ...

  9. day 71 crm(8) 权限组件的设置,以及权限组件的应用

    ---恢复内容开始--- 前情提要: strak 组件是增删改查组件 , 生活中,需求权限组件,  不足: 1,前后端不分离,   2, 空url也会刷新界面,造成资源浪费   3,如果角色忘记设置权 ...

随机推荐

  1. NewStar 信息分发系统设计

    目录 NewStar 信息分发系统设计 我想要怎么做 系统流程图 解释和初步的模板展示 NewStar 信息分发系统设计 我们在全世界发布网站本质就是向全世界分发我们的信息给客户/潜在客户,然后希望促 ...

  2. Chapter 18 MySQL NDB Cluster 7.3 and NDB Cluster 7.4渣翻

    Table of Contents 18.1 NDB Cluster Overview      18.2 NDB Cluster Installation      18.3 Configurati ...

  3. codesmith 在安装32位Oracle 客户端问题解决

    问题解决办法如下: https://blog.csdn.net/csdn1152789046/article/details/52248669

  4. CentOS6.5 环境安装配置

    一.GO环境配置 1.运行命令进入/usr/local/src目录:cd /usr/local/src 2.下载安装包:运行wget --no-check-certificate https://st ...

  5. Webpack webpack+gulp实现自动构建部署

    http://www.cnblogs.com/sloong/p/5826859.html

  6. css3的transform变换scale和translate等影响jQuery的position().top和offset().top

    css3的transform变换scale和translate等影响jQuery的position().top和offset().top

  7. 自定义列表dl

    语法格式 <dl> <dt>名词1</dt> <dd>名词1解释1</dd> <dd>名词1解释2</dd> ... ...

  8. Hadoop之—— WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform...

    [hadoop@hadoop000 hadoop]$ ldd --version ldd (GNU libc) 2.12 Copyright (C) Free Software Foundation, ...

  9. cms系统-帖子页面

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  10. 基于spark Mllib(ML)聚类实战

        写在前面的话:由于spark2.0.0之后ML中才包括LDA,GaussianMixture 模型,这里k-means用的是ML模块做测试,LDA,GaussianMixture 则用的是ML ...