django批量修改table_django-formset实现数据表的批量操作
什么是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实现数据表的批量操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2017年最新平安银行信用卡账单日修改方
- 下一篇: 交通银行买单吧跨行还信用卡相关问题分析