Django表單外鍵選項初始化的問題及解決方法
問題描述
先說明一下問題的由來:
Django的模型中經常會用ForeignKey來關聯其他表格數據
class MeasureTask(models.Model): taskname = models.CharField(max_length=LEN_FULLNAME, verbose_name="任務名稱") road = models.ForeignKey(Road, on_delete=models.CASCADE, verbose_name="設計路段") # 路面層,附加一個參數 ,指定這個層的厚度,相對於底層的厚度 # road_level = models.ForeignKey(RoadLevel, on_delete=models.CASCADE, verbose_name="路面層") level_thick = models.IntegerField(default=0, verbose_name="層厚(mm)") # ...
使用Django的ModelForm轉化為表單代碼如下:
class MeasureTaskNewForm(forms.ModelForm): class Meta: model = MeasureTask fields = ('taskname', 'staff', 'start_mileage', 'end_mileage', 'road', 'level_thick', 'step', 'equip', 'comment')
如果不做進一步處理,在網頁中使用這個From時,關聯字段會自動轉化為一個select控件,裡面包含瞭所有選項,如下圖:
實際應用時,需要對關聯的字段做一些選擇過濾。期望的結果如下:
解決方式
在From類中設置一個初始化函數:
class MeasureTaskNewForm(forms.ModelForm): class Meta: model = MeasureTask fields = ('taskname', 'staff', 'start_mileage', 'end_mileage', 'road', 'level_thick', 'step', 'equip', 'comment') # 對參數作初始化設置,導致返回之後的Form驗證失敗 def __init__(self, road_choices=None, *args, **kwargs): super(MeasureTaskNewForm, self).__init__(*args, **kwargs) if road_choices: self.fields['road'].choices = road_choices
應用這個類的方式如下,註意傳入參數的數據類型,
# 對關聯數據過濾 roads = Road.objects.filter(project=p_item) # 生成值,分別對應於 html 中 select->option 設置 choices = roads.values_list('id', 'name') dataform = MeasureTaskNewForm(road_choices=choices) # dataform = MeasureTaskNewFormShadow() return render(request, "mdata/html/measure_task_add.html", locals())
生成的html代碼:
<select name="road" id="id_road" class="form-control"> <option value="1">北四環主線</option> <option value="5">匝道A</option> </select>
到這裡生成的表單頁面沒有問題瞭,但是表單提交返回時如果還是用這個From來接收Request數據,則會出現數據校驗失敗的問題
if request.method == "POST": dataform = MeasureTaskNewForm(request.POST) # 這裡將出現校驗失敗的問題 if dataform.is_valid(): dataform.save() return redirect('mdata:measure_task', pid=p_item.id)
為瞭解決這個問題,另外做瞭一個沒有初始化函數的表單類來接收數據.
# 影子表單模型 class MeasureTaskNewFormShadow(forms.ModelForm): class Meta: model = MeasureTask fields = ('taskname', 'staff', 'start_mileage', 'end_mileage', 'road', 'level_thick', 'step', 'equip', 'comment')
if request.method == "POST": dataform = MeasureTaskNewFormShadow(request.POST) if dataform.is_valid(): dataform.save() return redirect('mdata:measure_task', pid=p_item.id)
感覺這裡應該有更好的方法,嘗試對Form的初始化函數做瞭一些修改,但是沒有成功。
參考資料
https://qastack.cn/programming/813418/django-set-field-value-after-a-form-is-initialized
http://hk.uwenku.com/question/p-vdjpsmjn-bes.html
https://www.itranslater.com/qa/details/2325790729974580224
到此這篇關於Django表單外鍵選項初始化的文章就介紹到這瞭,更多相關Django表單初始化內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Python Django模型詳解
- Django視圖類型總結
- Django與圖表的數據交互的實現
- Django中session進行權限管理的使用
- Django集成富文本編輯器summernote的實現步驟