我們有一個Django模型,ToolDataset和一個ModelForm,ToolForm。在Model中,每個實例或數據庫行稱爲數據集,主鍵稱爲dataset_id。第一次通過時,用戶填寫一個未綁定的表單並提交。從概念上講,這是用來驗證,保存和分析數據集的視圖代碼:爲什麼已知有效的Django模型實例在從數據庫檢索後失敗is_valid()?
if (request.method == 'POST') and (not dataset_id):
form = ToolForm(request.POST)
if form.is_valid():
new_dataset = form.save()
dataset_id = new_dataset.pk
results = analyze(form.cleaned_data)
else:
<validation error code>
我認爲到目前爲止,這是非常正常的。請注意,表單數據不會保存,除非數據有效,否則不會分配dataset_id。
現在過了一段時間,用戶想要返回到這個特定的舊數據集,也許要更改數據並重新分析它。所以,無論如何,一個網址的構成看起來像www.finesite.com/Tool/X/,其中X是與用戶想要使用的特定行數據對應的dataset_id。通過URL配置,視圖代碼的不同分支被調用時,我們認爲應該是這樣的:
if (request.method != 'POST') and (dataset_id):
oldset = get_object_or_404(ToolDataset, pk=dataset_id)
form = ToolForm(instance=oldset)
if form.is_valid():
results = analyze(form.cleaned_data)
else:
<validation error code that we expected would never run>
嗯,事實證明,這個數據集,這是有效的,當我們保存它,沒有按」現在驗證,這是一個驚喜。我們使用manage.py shell來檢查表單。下面是一些我們發現:
>>> form.is_valid()
False
>>> form.errors
{}
>>> form.non_field_errors()
[]
>>> form.is_bound
False
運行form.as_p()
產生什麼似乎是一個完整的形式。
一個非常能幹的人在django/forms/models.py中找到了一個未公開的API函數,稱爲model_to_dict()。他建議代位,
form = BXEEP_L_Form(model_to_dict(oldset), instance=oldset),
爲此,
form = BXEEP_L_Form(instance=oldset).
它現在 - 的形式是有效的,裝訂成冊,根據外殼 - 但我滿腹的疑問。爲什麼這個工作?爲什麼這是必要的?有沒有更標準的方法來做到這一點?看起來很常見並且不復雜的用例中使用未公開的內部函數似乎很奇怪。
如果我使用dataset_id作爲我的分析函數的參數,那將是一個小得多的參數來傳遞,但然後分析函數需要做一個數據庫查詢,並且我認爲這樣做的最終結果是要減慢事情下降了一點。真正控制整個過程的視圖使用get_object_or_404來部分獲取這些數據,以便將其呈現給頁面。由於這些數據已經存在,爲什麼要查詢數據庫兩次。爲什麼不把它傳遞給analyze()? – 2010-03-04 15:28:32
數據集包含工程設計問題的參數。當用戶經過一段時間後返回數據集時,可能是因爲他想要優化設計(調整參數)或者只是查看舊的結果。無論哪種情況,都必須再次進行分析,以便通過一系列計算的性能測量(稱爲統一檢查)來查看設計的當前狀態,這些測量不會保存,因此在重新計算之前無法顯示分析功能。 – 2010-03-04 15:31:26
我現在看到了你的第一點的含義。最好的想法是將分析函數的參數作爲模型實例,而不是form.cleaned_data。然後分析函數可以繼續,而is_valid()不必再次運行。 is_valid()用於驗證用戶輸入,因此它在這裏的使用是不必要的,因爲這是在前面完成的。除了一些重寫之外,這個改變沒有任何缺點。見下文。 – 2010-03-04 19:02:39