formset批量处理form表单数据
Formset(表单集)是多个表单的集合。Formset在Web开发中应用很普遍,它可以让用户在同一个页面上提交多张表单,一键添加多个数据
class StudentStudyRecordModel(forms.ModelForm): class Meta: model=StudentStudyRecord fields=['score','homework_note']
view视图
from django.forms.models import modelformset_factoryclass Student_study_record(View): def get(self,request): model_formset_cls=modelformset_factory(model=StudentStudyRecord,form=StudentStudyRecordModel,extra=0) queryset=StudentStudyRecord.objects.filter(classstudyrecord__id=request.GET.get('pk')) #批量操作的queryset formset=model_formset_cls(queryset=queryset) return render(request, 'students/Student_study_record.html', locals()) def post(self,request): model_formset_cls = modelformset_factory(model=StudentStudyRecord, form=StudentStudyRecordModel, extra=0) formset=model_formset_cls(request.POST) #与modelform校验基本一致,就是不用穿instance了 if formset.is_valid(): formset.save() return redirect('/class_study_record/') else: print('formset.errors##################',formset.errors) return self.get(request)
templates模版
<form action="" method="post" novalidate> <table class="table table-hover table-striped" style="margin-top: 20px"> <thead> <tr> <td>编号</td> <td>姓名</td> <td>考勤</td> <td>成绩</td> <td>批语</td> </tr> </thead> <tbody> {# 必须有,不然会报错#} {{ formset.management_form }} {% for form in formset %} <tr> <td>{{ form.id }}</td> # 必须有form.id <td>{{ form.instance.student }}</td> #instance是显示具体的某个对象的值,而不是多选框(不能修改) <td>{{ form.instance.get_record_display }}</td> <td>{{ form.score }}</td> <td>{{ form.homework_note }}</td> {% csrf_token %} </tr> {% endfor %} </tbody> </table> <button class=" btn btn-success btn-sm pull-right" style="margin: 30px;">提交</button> </form>
多个表单的集合,可以同时提交多个from表单中的数据,在web页面中,可以在同一个页面,提交多个form表单。
Django针对不同的formset提供了3种方法: formset_factory, modelformset_factory和inlineformset_factory。下面对modelformset_factory进行示例展示
from django.forms import modelformset_factory def study_record(request,courserecord_id): # modelformset_factory 支持在同一页面显示多个form,一个form就是作为一条记录,可以直接在本也米娜对from中的内容进行修改 formset = modelformset_factory(model=models.StudyRecord,form=StudyRecordForm,extra=0) formset_obj = formset(queryset=models.StudyRecord.objects.filter(course_record_id=courserecord_id)) if request.method == 'POST': formset_obj = formset(data=request.POST) if formset_obj.is_valid(): formset_obj.save() next = request.GET.get('next') print(next) return redirect(next) return render(request,'teacher/studyrecord_list.html',{'formset_obj':formset_obj}) 【注意】 初始化fromset时,使用的参数:model;form;extra=0,等于1时,会有一个额外的空选项 实例化fromset时,使用的参数:queryset
ModelForm中
class BaseForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 自定义操作,循环添加class操作,当遇到MultiSelectFormField或者forms.BooleanField框时,不加class类 for name, field in self.fields.items(): # if name == 'course' # 可以直接判断字段名 if isinstance(field, (MultiSelectFormField, forms.BooleanField)): # 判断字段类型是MultiSelectFormField, forms.BooleanField还可以根据需求继续添加到元组中,让他们的格式不接受form-control的样式 continue # 方式一: field.widget.attrs['class'] = 'form-control' # 方式二: # field.widget.attrs.update({'class': 'form-control'}) class StudyRecordForm(BaseForm): class Meta: model = models.StudyRecord fields = '__all__'
html中注意`{{ formset_obj.management_form }}`
<form action="" method="post"> {% csrf_token %} {{ formset_obj.management_form }} <div> <button class="btn btn-primary btn-sm">保存</button> </div> <table class="table table-hover" id="tableList"> <thead> <tr> <th>序号</th> <th>学生姓名</th> <th>考勤</th> <th>成绩</th> <th>批语</th> </tr> </thead> <tbody id="UserList"> {% for obj in formset_obj %} <tr class="relative" data-id="3"> {{ obj.id }} <td class="table-edit">{{ forloop.counter }} </td> <td class="table-edit">{# 让姓名编程不可修改项 #} <a href=""> {{ obj.instance.student }}</a> </td> <td>{{ obj.attendance }}</td> <td class="table-edit">{{ obj.score }}</td> <td class="table-edit">{{ obj.homework_note }}</td> <td class="hidden">{{ obj.course_record }}</td> <td class="hidden">{{ obj.student }}</td> {# 这两项隐藏的目的是,form表单提交数据时需要对其进行验证,二是不需要让使用者看见,因为他是默认的,不需要跟进修改 #} </tr> {% endfor %} </tbody> </table> </form>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界