效果图:

增加页面:

编辑页面:

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

数据库

  1. from django.db import models
  2.  
  3. class Menu(models.Model):
  4. """
  5. 菜单表
  6. """
  7. title = models.CharField(verbose_name='菜单名称', max_length=32)
  8. icon = models.CharField(verbose_name='图标', max_length=32)
  9.  
  10. def __str__(self):
  11. return self.title
  12.  
  13. class Permission(models.Model):
  14. """
  15. 权限表
  16. """
  17. title = models.CharField(verbose_name='标题', max_length=32)
  18. url = models.CharField(verbose_name='含正则的URL', max_length=128)
  19.  
  20. name = models.CharField(verbose_name='URL的别名', max_length=32, unique=True)
  21.  
  22. menu = models.ForeignKey(verbose_name='所属菜单', to='Menu', null=True, blank=True,
  23. help_text='null表示不是菜单;非null表示是二级菜单', on_delete=models.CASCADE)
  24.  
  25. pid = models.ForeignKey(verbose_name='关联的权限', to='Permission', null=True, blank=True, related_name='parents',
  26. help_text='对于非菜单权限需要选择一个可以成为菜单的权限,用于做默认展开和选中菜单',
  27. on_delete=models.CASCADE)
  28.  
  29. def __str__(self):
  30. return self.title

一、配置路由

  1. from django.urls import path
  2. from formset import views
  3.  
  4. urlpatterns = [
  5. path('multi/add', views.multi_add),
  6. path('multi/edit', views.multi_edit),
  7. ]

二、forms表单验证

  1. from django import forms
  2.  
  3. from formset import models
  4.  
  5. class MultiPermissionForm(forms.Form):
  6. title = forms.CharField()
  7. url = forms.CharField()
  8. name = forms.CharField()
  9. menu_id = forms.ChoiceField(
  10. choices=[(None, '----------')],
  11. required=False
  12. )
  13. pid_id = forms.ChoiceField(
  14. choices=[(None, '----------')],
  15. required=False
  16. )
  17.  
  18. def __init__(self, *args, **kwargs):
  19. super().__init__(*args, **kwargs)
  20. self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
  21. self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
  22. menu__isnull=True).values_list('id', 'title')
  23.  
  24. class MultiUpdatePermissionForm(forms.Form):
  25. id = forms.IntegerField(
  26. widget=forms.HiddenInput()
  27. )
  28. title = forms.CharField()
  29. url = forms.CharField()
  30. name = forms.CharField()
  31. menu_id = forms.ChoiceField(
  32. choices=[(None, '----------')],
  33. required=False
  34. )
  35. pid_id = forms.ChoiceField(
  36. choices=[(None, '----------')],
  37. required=False
  38. )
  39.  
  40. def __init__(self, *args, **kwargs):
  41. super().__init__(*args, **kwargs)
  42. self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
  43. self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
  44. menu__isnull=True).values_list('id', 'title')

三、视图函数

  1. from django.forms import formset_factory
  2. from django.shortcuts import render, HttpResponse
  3.  
  4. from formset import models
  5. from formset.forms.formset import MultiPermissionForm, MultiUpdatePermissionForm
  6.  
  7. def multi_add(request):
  8. """
  9. 批量增加
  10. :param request:
  11. :return:
  12. """
  13.  
  14. formset_class = formset_factory(MultiPermissionForm, extra=5) # 在内部生成五个form表单
  15.  
  16. if request.method == 'GET':
  17. formset = formset_class()
  18. return render(request, 'multi_add.html', {'formset': formset})
  19.  
  20. formset = formset_class(data=request.POST) # 储存的所有信息,包括html标签
  21. if formset.is_valid():
  22. no_repeat_field = True
  23.  
  24. # 要把cleaned_data放到for循环上面,因为在下面一旦cleaned_data检测到错误信息就会报错。里面储存了一个个form[{},{},{}......]
  25. form_list = formset.cleaned_data # 检查formset中有没有错误信息,没有则将用户提交的数据取到。有错误信息就报错
  26. for num in range(0, formset.total_form_count()):
  27. form = form_list[num] # 一个具体的form
  28. if not form:
  29. continue
  30. try:
  31. # 下面的方式和model.Permission.object.create(**row)效果一样,这里用这种方式是为了捕获唯一性错误
  32. permission_obj = models.Permission(**form)
  33. permission_obj.validate_unique() # 检查当前对象在数据库是否存在唯一的
  34. permission_obj.save()
  35. except Exception as e:
  36. formset.errors[num].update(e) # 把错误信息放到对应的form里面
  37. no_repeat_field = False
  38.  
  39. if no_repeat_field:
  40. return HttpResponse('提交成功')
  41. else:
  42. return render(request, 'multi_add.html', {'formset': formset})
  43. return render(request, 'multi_add.html', {'formset': formset})
  44.  
  45. def multi_edit(request):
  46. formset_class = formset_factory(MultiUpdatePermissionForm, extra=0) # 默认等于1,如果不想让它多增加一个,就把默认改成0
  47. if request.method == 'GET':
  48. formset = formset_class(
  49. initial=models.Permission.objects.all().values('id', 'title', 'name', 'url', 'menu_id', 'pid_id')
  50. )
  51. return render(request, 'multi_edit.html', {'formset': formset})
  52.  
  53. formset = formset_class(data=request.POST)
  54. if formset.is_valid():
  55. no_repeat_field = True
  56. form_list = formset.cleaned_data
  57. for num in range(0, formset.total_form_count()):
  58. form = form_list[num]
  59. if not form:
  60. continue
  61. permission_id = form.pop('id')
  62. try:
  63. permission_obj = models.Permission.objects.filter(id=permission_id).first()
  64. for key, value in form.items():
  65. setattr(permission_obj, key, value) # 更新数据库的字段
  66. permission_obj.validate_unique()
  67. permission_obj.save()
  68. except Exception as e:
  69. formset.errors[num].update(e)
  70. no_repeat_field = False
  71. if no_repeat_field:
  72. return HttpResponse("提交成功")
  73. else:
  74. return render(request, 'multi_edit.html', {'formset': formset})
  75. return render(request, 'multi_edit.html', {'formset': formset})

四、模板渲染

multi_add.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css">
  7. </head>
  8. <body>
  9.  
  10. <div class="container" style="margin-top: 100px">
  11. <div class="row">
  12. <form action="" method="post" novalidate>
  13. {% csrf_token %}
  14. {{ formset.management_form }}
  15. <table class="table table-hover table-stripped" border="1">
  16. <thead>
  17. <tr>
  18. <th>标题</th>
  19. <th>URL</th>
  20. <th>Name</th>
  21. <th>菜单</th>
  22. <th>父权限</th>
  23. </tr>
  24. </thead>
  25. <tbody>
  26. {% for form in formset %}
  27. <tr>
  28. {% for field in form %}
  29. <td>
  30. {{ field }}
  31. <span style="color:red">{{ field.errors.0 }}</span>
  32. </td>
  33. {% endfor %}
  34. </tr>
  35. {% endfor %}
  36. </tbody>
  37. </table>
  38. <hr/>
  39. <input type="submit" value="提交" class="btn btn-primary">
  40. </form>
  41. </div>
  42. </div>
  43.  
  44. </body>
  45. </html>

multi_edit.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css">
  7. </head>
  8. <body>
  9.  
  10. <div class="container" style="margin-top: 100px">
  11. <div class="row">
  12. <form action="" method="post" novalidate>
  13. {% csrf_token %}
  14. {{ formset.management_form }}
  15. <table class="table table-hover table-stripped" border="1">
  16. <thead>
  17. <tr>
  18. <th>标题</th>
  19. <th>URL</th>
  20. <th>Name</th>
  21. <th>菜单</th>
  22. <th>父权限</th>
  23. </tr>
  24. </thead>
  25. <tbody>
  26. {% for form in formset %}
  27. <tr>
  28. {% for field in form %}
  29. {% if forloop.first %}
  30. {{ field }}
  31. {% else %}
  32. <td>
  33. {{ field }}
  34. <span style="color:red">{{ field.errors.0 }}</span>
  35. </td>
  36. {% endif %}
  37. {% endfor %}
  38. </tr>
  39. {% endfor %}
  40. </tbody>
  41. </table>
  42. <hr/>
  43. <input type="submit" value="提交" class="btn btn-primary">
  44. </form>
  45. </div>
  46. </div>
  47.  
  48. </body>
  49. </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. (三)Redis两种持久化方案

    Redis的持久化策略:2种 RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘.RDB是Redis默认采用的持久化方 ...

  2. (一)Redis简介和安装

    1       Redis介绍 1.1      什么是NoSql 为了解决高并发.高可扩展.高可用.大数据存储问题而产生的数据库解决方案,就是NoSql数据库. NoSQL,泛指非关系型的数据库,N ...

  3. EL_JSTL

    EL(Expression Language)EL表达式 作用:在JSP中消灭java代码 语法: "${ }" 用法:参考jsp页面 //Servlet中,: User user ...

  4. jsp连接sqlite、Sqlite相对路径绝对路径问题(转)

    转自  http://blog.csdn.net/sxy12138/article/details/52304884 假如在java中, # 数据库连接jdbc.jdbc-url=jdbc:sqlit ...

  5. html便民查询各个工具类实例代码分享(支持pc和移动端)

    1.手机号码查询 <iframe id="api_iframe_51240" name="api_iframe_51240" src="&quo ...

  6. echarts折柱混合(图表数据与x轴对应显示)

    一天24个小时,每个小时不一定都有对应的数据,所以后台给出的数据,只有每个时间点对应的数据,比如4点,给的是112,5点的242,其他时间没有,则只显示4点,5点时候的数据,那么现在对应的时间点就是后 ...

  7. python3基础07(进程操作及执行系统级命令等)

    #subprocess 创建子进程 连接输入 输出 管道错误,及获取他们的状态,可执行操作系统级的命令# subprocess.run(args, *, stdin=None, input=None, ...

  8. linux下如何实现mysql数据库定时自动备份

    概述   备份是容灾的基础,是指为防止系统出现操作失误或系统故障导致数据丢失,而将全部或部分数据集合从应用主机的硬盘或阵列复制到其它的存储介质的过程.而对于一些网站.系统来说,数据库就是一切,所以做好 ...

  9. Jsoup查找dom元素

    package com.open1111.jsoup; import org.apache.http.HttpEntity;import org.apache.http.client.methods. ...

  10. mif文件生成方法

    mif文件就是存储器初始化文件,即memory initialization file,用来配置RAM或ROM中的数据.常见生成方法: Quartus自带的mif编辑器生成 mif软件生成 高级编程语 ...