91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

django formset實現數據表的批量操作的示例代碼

發布時間:2020-08-29 09:49:05 來源:腳本之家 閱讀:143 作者:liuxu2019 欄目:開發技術

什么是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
<form method="post">
  {% csrf_token %}
  {{ formset.management_form }}
  <table 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 >{{ field.errors.0 }}</span></td>
        {% endfor %}
      </tr>
    {% endfor %}
    </tbody>
  </table>
  <input type="submit" value="提交">
</form>

批量編輯

批量編輯和批量增加大體是一致的,但是存在不同的使用區別。實例化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}} ,頁面將不會顯示。

<form method="post">
  {% csrf_token %}
  {{ formset.management_form }}
  <table 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 >{{ field.errors.0 }}</span></td>
          {% endif %}
        {% endfor %}
      </tr>
    {% endfor %}
    </tbody>
  </table>
  <input type="submit" value="提交">
</form>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宜州市| 三穗县| 绥滨县| 随州市| 石棉县| 桓台县| 太仓市| 岢岚县| 合川市| 新沂市| 咸阳市| 来安县| 佛坪县| 霍山县| 珠海市| 宁波市| 延川县| 商洛市| 博客| 竹山县| 蒲城县| 临城县| 明溪县| 磐安县| 宁远县| 华容县| 六安市| 黄山市| 长兴县| 新巴尔虎左旗| 壤塘县| 九龙城区| 特克斯县| 板桥市| 禹州市| 华安县| 民乐县| 商城县| 略阳县| 阜新市| 岳池县|