什么是formset

我们知道forms组件是用来做表单验证,更准确一点说,forms组件是用来做数据库表中一行记录的验证。有forms组件不同,formset是同科同时验证表中的多行记录,即formset是做表单批量验证的组件。

批量添加

首先要实例化formset对象,对象初始化时需要提供操作表的forms表单类,参数extra用来显示验证几行数据。将实例化的formset对象传递给前端页面,前端模板通过两层循环:第一层循环form,第二层循环form中的字段。当GET请求时,直接将实例化的formset对象传递给前端。当POST请求时,批量验证表单,当所有数据都没有问题时,后台数据库保存数据。

后台保存数据时,有两种方式:第一种方式简洁,但是无法捕获字段唯一约束的错误;因此使用formset批量添加数据时最好使用第二中方式,手动捕获唯一约束错误信息并交给formset送到前端页面显示。

models.Permission.objects.create(**row)

obj = models.Permission(**row) | obj.save()

唯一约束错误信息捕获的过程,需要使用obj.validate_unique()判断该对象是否满足唯一约束,如果不满足则通过异常捕获操作,捕获异常信息。通过formset.errors[i].update(e)把错误信息放入formset中送到前端页面显示。之所以这样做,是因为通过forms组件的验证时无法捕获唯一约束的错误。因此这里通过手动收集错误信息并放入forset中。

此外,如果前端页面渲染的表单没有填写数据,直接提交是不会报错的。formset默认只要不改动字段就不会对该行数据做验证。只要填写一个字段,该行数据则会做表单验证。

# views.py

def multi_add(request):

"""

批量添加

:param request:

:return:

"""

formset_class = formset_factory(MultiPermissionForm, extra=2)

if request.method == 'GET':

formset = formset_class()

return render(request, 'multi_add.html', {'formset': formset})

formset = formset_class(data=request.POST)

if formset.is_valid():

flag = True

# 检查formset中没有错误信息,则讲用户提交的数据获取到。

post_row_list = formset.cleaned_data

for i in range(0, formset.total_form_count()):

row = post_row_list[i]

if not row:

continue

try:

obj = models.Permission(**row)

obj.validate_unique() # 检查当前对象在数据库是否存在唯一的异常。

obj.save()

except Exception as e:

formset.errors[i].update(e)

flag = False

if flag:

return HttpResponse('提交成功')

else:

return render(request, 'multi_add.html', {'formset': formset})

return render(request, 'multi_add.html', {'formset': formset})

前端模板通过两层循环:第一层循环formset得到每一个form,第二层循环form得到每一个字段。与forms组件使用一样,需要手动添加form表单和input提交数按钮及csrf_token跨域伪造请求。此外,使用formset,还需要增加{{ formset.management_form }} , 使用哪个formset就增加哪个formset.management_form.

# multi_add.html

{% csrf_token %}

{{ formset.management_form }}

标题URLNAME菜单父权限

{% for form in formset %}

{% for field in form %}

{{ field }} {{ field.errors.0 }}

{% endfor %}

{% endfor %}

批量编辑

批量编辑和批量增加大体是一致的,但是存在不同的使用区别。实例化formset对象时默认extra=1,需要手动修改为extra=0;GET请求,页面需要显示默认值,通过参数initial赋值列表内部嵌套字典的数据结构的数据。且需要传递每行数据的id,告诉formset需要修改的数据id。此时使用的forms类相比批量添加使用的类多一个id字段,id = forms.IntegerField( widget=forms.HiddenInput()),默认隐藏的字段,前端页面不显示。

同理也会遇到唯一约束错误,使用循环和反射为每个字段做数据更新赋值,然后再提交数据库保存。

def multi_edit(request):

formset_class = formset_factory(MultiUpdatePermissionForm, extra=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():

# 检查formset中没有错误信息,则讲用户提交的数据获取到。

post_row_list = formset.cleaned_data

flag = True

for i in range(0, formset.total_form_count()):

row = post_row_list[i]

if not row:

continue

permission_id = row.pop('id')

try:

permission_object = models.Permission.objects.filter(id=permission_id).first()

for key, value in row.items():

setattr(permission_object, key, value)

permission_object.validate_unique()

permission_object.save()

except Exception as e:

formset.errors[i].update(e)

flag = False

if flag:

return HttpResponse('提交成功')

else:

return render(request, 'multi_edit.html', {'formset': formset})

return render(request, 'multi_edit.html', {'formset': formset})

前端模板循环显示每个字段时,要判断是否是第一个id字段,如果是第一个就直接{{field}},页面将不会显示。

{% csrf_token %}

{{ formset.management_form }}

标题URLNAME菜单父权限

{% for form in formset %}

{% for field in form %}

{% if forloop.first %}

{{ field }}

{% else %}

{{ field }} {{ field.errors.0 }}

{% endif %}

{% endfor %}

{% endfor %}

标签:form,request,django,forms,数据表,id,formset,row

来源: https://www.cnblogs.com/liuxu2019/p/11992573.html

django批量修改table_django-formset实现数据表的批量操作相关推荐

  1. django批量修改table_django formset实现数据表的批量操作的示例代码

    什么是formset 我们知道forms组件是用来做表单验证,更准确一点说,forms组件是用来做数据库表中一行记录的验证.有forms组件不同,formset是同科同时验证表中的多行记录,即form ...

  2. django批量修改table_Django 使用 modelformset 组件批量修改表单数据

    1.models.py: class StudentStudyRecord(models.Model): ''' 学生学习记录 ''' student = models.ForeignKey(verb ...

  3. django批量修改table_Django 数据库表多对多的创建和增删改查

    前面已经学习了在Django里面如何对单表的操作,同时也学习了1对多(单个外键)的表的操作.接下来,我们看看多对多(多个外键)的关系如何创建和管理. 比如说,我们有一个主机表,也有一个应用程序表,一个 ...

  4. django批量修改table_Django修改桥表(Django modify bridge table)

    Django修改桥表(Django modify bridge table) 我的django应用程序中有两个模型,事件/用户,它们具有多对多的关系. 活动可以有很多与会者(用户). 用户可以参加很多 ...

  5. django批量修改table_django restframework 多对多的批量修改,基于逻辑删

    模型: class LogisticQuerySet(QuerySet): def delete(self): self.update(is_delete=True) class BookManage ...

  6. MySQL批量修改数据库中的数据表名称

    1.一种使用存储过程解决,结果,总是如下提示 Expression #3 of SELECT list is not in GROUP BY clause and contains n 2.使用 CO ...

  7. Django 之 Models(Models 模型 数据表关系)

    Models 模型 ORM django连接数据库 models类的使用 定义和数据库表映射的类 字段常用参数 数据库的迁移 数据相关操作 查看数据库中的数据 查找数据 添加数据 常见查找方法 数据库 ...

  8. 批量修改table和index 的表空间

    由于开发人员把ess 项目下的大部分对象放到user 表空间中,用imp/exp 导入正式库后,ess用户的对象还是在users 表空间中.为了把ESS 的对象放到ess 默认的表空间ess中,我按如 ...

  9. 反思一次线上bug的修改:没法看数据表的一次线上问题处理

    线上问题:点击保存后,关联的后台显示不了修改的数据 困难点:线上数据库连接不了需要vpn 解决方法: 沟通进行确定数据表的数据,确定数据保存存在问题 根据master进行新建分支fix-bug ,排查 ...

最新文章

  1. 高性能集群软件Keepalived之基础知识篇
  2. 我能使用这个Intent吗?
  3. 深圳网络推广谈论网站收录后的内容还能不能修改?
  4. 解析远程服务器响应错误,远程服务器返回一个意外的响应:(400)错误的请求,WCF...
  5. boost::spirit模块实现演示自定义的、用户定义的类型如何作为标记值类型轻松地与词法分析器集成
  6. 前端做CRM管理系统是做什么_代办行业的CRM客户关系管理系统应该是什么样子的?...
  7. 为什么数据科学家需要承担开发运维的工作?
  8. 超实用的脚本——检查oracle数据库是否存在潜伏的比特币勒索病毒
  9. Eclipse下PHP开发 插件安装
  10. 关于备考软考过程中历年真题的说明
  11. JAVA实现网页版斗地主_使用Java实现简单的斗地主案例
  12. 解决Unity TextMeshPro 不能显示中文问题
  13. DDR3各个频率详解
  14. iOS之推荐六款不错的 iOS 15 Safari 浏览器扩展
  15. python处理excel——创建excel工作簿和工作表并录入信息(openpyxl库)
  16. SQLite3 获取最小可用ID,ID无需包含1
  17. DLbest系列1——GAN生成对抗网络2
  18. pg中多值列_PostgreSQL中列的statistics属性
  19. 连连看修改(golang)
  20. 前端:使用BootStrap搭建一个简单的网页

热门文章

  1. oracle中xml如何存储过程,oracle存储过程生成xml文件
  2. oracle错误12637,TNS-12537 TNSconnection closed ORA-609错误处理
  3. 鸿蒙思维和小央美,中心路汝南路站附近艺术培训
  4. zabbix触发器表达式
  5. [原创]前端工作了一段时间经验总结,献给做前端的同学
  6. day3-python学习笔记(二)list(数组)
  7. .NET CORE在ubuntu1604上运行
  8. 将自己的女朋友的话和视频做为启动音乐和启动动画(XP)
  9. [Leetcode][第1025题][JAVA][除数博弈][数学][递推]
  10. matlab如何找出最小的数据,读取数据并找出全部数据的最大值和最小值