簡體   English   中英

Django, form.is_valid() 它檢查什么?

[英]Django, form.is_valid() What does it check?

我不使用models.form的形式我收到並存儲了request.POST和request.FILES的每一項我將驗證function。 所以我想知道它做了什么驗證。 (例如輸入為空等)

手動處理request.POSTrequest.FILES確實是個壞主意:數據可以“偽造”,並且關於如何使用<form>構造請求的 HTML 規范有一些特殊性。 例如,如果復選框<input type="checkbox" name="somename">選中,則它不會出現在請求中,而如果選中,則它不會出現在請求中。

因此,第一個問題是表單的所有字段本身都不會出現在request.POST中,這本身不是問題:可能不需要某些字段。 如果值出現在request.POSTrequest.FILES中,則 Django 表單將檢查所有必需的字段。

接下來表單將開始清理數據。 這意味着它將所有字符串的數據轉換為更合適的數據類型。 例如對於DateField ,它將嘗試將其轉換為date object。 它通常會嘗試DATE_INPUT_FORMAT設置[Django-doc]中的所有格式,但是您可以在構造DateField時對其進行自定義,從而為該特定字段使用不同的格式。 某些字段,例如BooleanField將例如查看該字段是否確實在request.POST中,然后返回True否則返回False ,因此這不僅僅是request.POST中值的簡單映射,因為該值可能不是那里。

清理不僅對對應的 Python 對象上的 map 字符串,還可以對這些字段進行一些(小)后處理。 例如,默認情況下, CharField修剪字符串,從而刪除前導和尾隨空格,而ModelChoiceField將從數據庫中為該主鍵選擇相應的 model object。 表單字段還有一個空值列表:被認為是空的值。 例如對於CharField ,您可以將'/'設置為空值。 然后它將因此將斜杠視為該字段為空。

可以創建比已定義的表單字段更多的表單字段,因此這意味着很容易構建例如一個EANField ,您可以在其中實現一次清理,但這意味着您需要為每個視圖都這樣做。 因此,表單字段用於通過在字段中實施清理過程來使清理更可重用。

接下來是表單字段的驗證。 雖然 HTML 中的文本字段可以具有<input type="text" minlength="6" maxlength="24"> ,但您永遠不能依賴瀏覽器將作為值發布的內容:確實可以偽造POST 請求,所以雖然HTML 表單可能旨在阻止人們選擇少於六個字符或多於二十四個字符的用戶名,您不能確定 POST 請求中是否會出現這種情況。 表單字段可以通過validators=… [Django-doc] :一組可調用的,在項目無效的情況下引發驗證錯誤。 例如對於CharField ,如果您為min_length=…和/或max_length=…驗證器傳遞一個值,它將因此檢查這些。 它將所有的ValidationError添加到一個列表中,這在視圖中實現通常很麻煩:大多數驗證數據的視圖將檢查某個條件,例如密碼字符的最小長度,如果失敗,則報告錯誤,而使用Form ,它還可以添加一個額外的錯誤,您應該使用至少一位數字。 該表單將對所有表單字段執行此操作,從而構建一個將字段名稱映射到錯誤列表的字典。

如果所有表單字段都成功返回驗證數據,那么表單將創建一個屬性.cleaned_data [Django-doc] ,將字段名稱映射到該表單字段已清理的相應值。 但是,可以進一步向Form添加額外的清理和驗證。

然后在表單級別本身進行驗證。 method.如果你想稍微自定義表單,然后形成一個名為field_name的字段,你可以實現一個方法。 此方法可以訪問.cleaned_data字典,然后對該字段運行附加驗證並引發ValidationError ,此外還可以“清理” function,例如通過返回不同類型的 object 或對數據進行一些后處理然后返回。 因此,表單將收集這些值並使用這些清理后的值更新字典。 此外,如果該方法引發ValidationError ,該錯誤將被添加到該特定字段的.errors中。

之后,表單將調用.clean()方法[Django-doc] 這將對整個表單執行清理。 實際上,既然所有字段都已單獨清理,那么字段組合可能仍然存在錯誤。 例如兩個密碼字段是否匹配。 因此, clean方法通常會處理.cleaned_data屬性中的多個字段,並返回例如該字典或另一個 object。 如果您在此處引發ValidationError ,則該錯誤將被放入'__all__'鍵下的.errors中,因為這與特定字段無關。

對於ModelForm [Django-doc] ,驗證還沒有結束。 確實,model 本身還是可以進行一些驗證的。 它將使用已清理數據的值更新包裝在表單中的實例,並在實例上調用.full_clean()方法[Django-doc] ,稍后還會調用.validate_unique(…)方法[Django-doc]驗證對於應該是唯一的字段(具有unique=True ),這些確實是唯一的。 最后一項任務通常比乍看之下更復雜,因為如果在表單中編輯實例,則在數據庫中的檢查應該排除您正在編輯的當前實例。

只有在所有這些驗證之后, FormModelForm才會接受更改,然后.is_valid()將返回True 如果其中一個步驟因此失敗,錯誤將被添加到.errors中,因此.errors將嘗試構建一個字典來嘗試報告數據的所有問題。 如果您重新呈現表單,這很有用,因為這樣可以將錯誤放在相應字段旁邊,因此用戶可以獲得有關數據的所有問題的反饋,而不是表單遇到的第一個問題,因為這可能導致許多嘗試最終修復表單。

總結一下: Form中有很多邏輯可以驗證和清理數據。 試圖在視圖中實現這一點是一個普遍的錯誤。 在視圖中正確執行此操作很麻煩,但也不是很靈活:例如,如果您想為密碼添加額外的驗證器,則需要做很多工作才能實現,尤其是如果您想這樣做在多個視圖中。 Forms 被創建用於與表單字段驗證器、唯一性檢查等可重用組件一起使用。它也非常強大,因為它旨在驗證可能被偽造的請求數據,因此沒有被 HTML 屬性正確驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM