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" >
<option value="https://www.cnblogs.com/wujbclzw/archive/2021/04/29/1">北四環主線</option>
<option value="https://www.cnblogs.com/wujbclzw/archive/2021/04/29/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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/281387.html
標籤:其他
