简体   繁体   English

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

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

I do not use the form of models.form I received and stored each items of request.POST and request.FILES I will make my validation function.我不使用models.form的形式我收到并存储了request.POST和request.FILES的每一项我将验证function。 So I wonder what validation it does.所以我想知道它做了什么验证。 (ex. input is empty, etc.) (例如输入为空等)

Manually processing request.POST and request.FILES is really a bad idea: the data can be "forged", and the HTML specifications on how the request is constructed with a <form> have some peculiarities.手动处理request.POSTrequest.FILES确实是个坏主意:数据可以“伪造”,并且关于如何使用<form>构造请求的 HTML 规范有一些特殊性。 For example if a checkbox <input type="checkbox" name="somename"> is not checked, then it does not appear in the request, whereas if it is checked, it appears with no value in the request.例如,如果复选框<input type="checkbox" name="somename">选中,则它不会出现在请求中,而如果选中,则它不会出现在请求中。

A first problem is thus that not per se all fields of the form will appear in the request.POST , that is not per se a problem: some fields might not be required.因此,第一个问题是表单的所有字段本身都不会出现在request.POST中,这本身不是问题:可能不需要某些字段。 The Django form will thus check for all fields that are required, if the value appears in request.POST and request.FILES .如果值出现在request.POSTrequest.FILES中,则 Django 表单将检查所有必需的字段。

Next the form will start cleaning the data.接下来表单将开始清理数据。 This means that it converts the data, which are all strings, to a more suitable datatype.这意味着它将所有字符串的数据转换为更合适的数据类型。 For example for a DateField , it will try to convert this to a date object.例如对于DateField ,它将尝试将其转换为date object。 It will normally try all formats in the DATE_INPUT_FORMAT setting [Django-doc] , but you can customize that when you construct a DateField to thus use a different format for that specific field.它通常会尝试DATE_INPUT_FORMAT设置[Django-doc]中的所有格式,但是您可以在构造DateField时对其进行自定义,从而为该特定字段使用不同的格式。 Some fields, like a BooleanField will for example look if the field is indeed in the request.POST and then return True and otherwise False , so this is not just a simple mapping of the value in request.POST , since that value might not be there.某些字段,例如BooleanField将例如查看该字段是否确实在request.POST中,然后返回True否则返回False ,因此这不仅仅是request.POST中值的简单映射,因为该值可能不是那里。

Cleaning does not only map strings on corresponding Python objects, it can also do some (small) post-processing on these fields.清理不仅对对应的 Python 对象上的 map 字符串,还可以对这些字段进行一些(小)后处理。 For example a CharField will by default trim the string, and thus remove leading and trailing spaces, whereas a ModelChoiceField will pick the corresponding model object for that primary key from the database.例如,默认情况下, CharField修剪字符串,从而删除前导和尾随空格,而ModelChoiceField将从数据库中为该主键选择相应的 model object。 A form field has also a list of empty values : values that are considered to be empty.表单字段还有一个空值列表:被认为是空的值。 For example for a CharField , you can set '/' as an empty value.例如对于CharField ,您可以将'/'设置为空值。 It will then thus consider the slash as the field being empty.然后它将因此将斜杠视为该字段为空。

One can create extra form fields than the ones that are defined, and this thus means that it is easy to construct for example an EANField where you implement the cleaning once, but that would mean that you need to do that for every view.可以创建比已定义的表单字段更多的表单字段,因此这意味着很容易构建例如一个EANField ,您可以在其中实现一次清理,但这意味着您需要为每个视图都这样做。 Form fields are thus used to make cleaning more reusable by implementing the cleaning process into the field.因此,表单字段用于通过在字段中实施清理过程来使清理更可重用。

Next in line are validations on the form fields.接下来是表单字段的验证。 While a text field in HTML can have a <input type="text" minlength="6" maxlength="24"> , you can nevery rely on what the browser will post as values: indeed POST requests can be forged , so while the HTML form might intent to prevent people from picking a username with less than six characters, or more than twenty-four characters, you can not be sure that this will be the case in the POST request.虽然 HTML 中的文本字段可以具有<input type="text" minlength="6" maxlength="24"> ,但您永远不能依赖浏览器将作为值发布的内容:确实可以伪造POST 请求,所以虽然HTML 表单可能旨在阻止人们选择少于六个字符或多于二十四个字符的用户名,您不能确定 POST 请求中是否会出现这种情况。 A form field can be passed validators=… [Django-doc] : a set of callables that raise a validation error in case the item is not valid.表单字段可以通过validators=… [Django-doc] :一组可调用的,在项目无效的情况下引发验证错误。 For example for a CharField , if you pass a value for the min_length=… and/or max_length=… validators, it will thus check these.例如对于CharField ,如果您为min_length=…和/或max_length=…验证器传递一个值,它将因此检查这些。 It will add all ValidationError s to a list, which is often cumbersome to implement in a view: most views that validate data will check a certain condition, for example the minimum length of the characters for a password, and if that fails, report an error, whereas with a Form , it can also add an extra error that you should use at least one digit.它将所有的ValidationError添加到一个列表中,这在视图中实现通常很麻烦:大多数验证数据的视图将检查某个条件,例如密码字符的最小长度,如果失败,则报告错误,而使用Form ,它还可以添加一个额外的错误,您应该使用至少一位数字。 The form will do that for all form fields, and thus construct a dictionary mapping the name of the fields to a list of errors.该表单将对所有表单字段执行此操作,从而构建一个将字段名称映射到错误列表的字典。

If all the form fields successfully return validate the data, then the form will create an attribute .cleaned_data [Django-doc] that maps the names of the fields to the corresponding value that has been cleaned by that form field.如果所有表单字段都成功返回验证数据,那么表单将创建一个属性.cleaned_data [Django-doc] ,将字段名称映射到该表单字段已清理的相应值。 One can however further add additional cleaning and validation to the Form .但是,可以进一步向Form添加额外的清理和验证。

Then there are validations at the form level itself.然后在表单级别本身进行验证。 If you want to slightly customize the form, then form a field named field_name , you can implement a clean_ field_name method.如果你想稍微自定义表单,然后形成一个名为field_name的字段,你可以实现一个clean_ field_name方法。 This method can access the .cleaned_data dictionary, and then run additional validation on that field and raise a ValidationError , and furthermore "clean" the function, for example by returing an object of a different type, or doing some post-processing on the data that is then returned.此方法可以访问.cleaned_data字典,然后对该字段运行附加验证并引发ValidationError ,此外还可以“清理” function,例如通过返回不同类型的 object 或对数据进行一些后处理然后返回。 The Form will thus collect these values and update the dictionary with these cleaned values.因此,表单将收集这些值并使用这些清理后的值更新字典。 Furthermore if the method raises a ValidationError , the error will be added to the .errors for that specific field.此外,如果该方法引发ValidationError ,该错误将被添加到该特定字段的.errors中。

After that, the form will call the .clean() method [Django-doc] .之后,表单将调用.clean()方法[Django-doc] This will perform cleaning on the entire form.这将对整个表单执行清理。 Indeed, now that all fields are cleaned individually, it might still be possible that there are errors about the combination of the fields.实际上,既然所有字段都已单独清理,那么字段组合可能仍然存在错误。 For example whether the two password fields match.例如两个密码字段是否匹配。 Usually the clean method will thus work with multiple fields in the .cleaned_data attribute, and return for example that dictionary, or another object.因此, clean方法通常会处理.cleaned_data属性中的多个字段,并返回例如该字典或另一个 object。 If you raise a ValidationError here, the error will be put in the .errors under the '__all__' key, since this is not related to a specific field.如果您在此处引发ValidationError ,则该错误将被放入'__all__'键下的.errors中,因为这与特定字段无关。

For a ModelForm [Django-doc] , the validation is not over yet.对于ModelForm [Django-doc] ,验证还没有结束。 Indeed, the model itself can still have some validation.确实,model 本身还是可以进行一些验证的。 It will update the instance wrapped in the form with the values of the cleaned data, and call the .full_clean() method [Django-doc] on the instance, and later also call the .validate_unique(…) method [Django-doc] to validate that for fields that should be unique (have unique=True ), these are indeed unique.它将使用已清理数据的值更新包装在表单中的实例,并在实例上调用.full_clean()方法[Django-doc] ,稍后还会调用.validate_unique(…)方法[Django-doc]验证对于应该是唯一的字段(具有unique=True ),这些确实是唯一的。 That last task is often more complicated than it looks at first sight, since if the instance is edited in the form, the check in the database, should exclude the current instance you are editing.最后一项任务通常比乍看之下更复杂,因为如果在表单中编辑实例,则在数据库中的检查应该排除您正在编辑的当前实例。

Only after all these validation, the Form or ModelForm will accept the change, and then .is_valid() will return True .只有在所有这些验证之后, FormModelForm才会接受更改,然后.is_valid()将返回True If in one of the steps thus fails, the error will be added to the .errors , and thus .errors will try to construct a dictionary that tries to report all the problems with the data.如果其中一个步骤因此失败,错误将被添加到.errors中,因此.errors将尝试构建一个字典来尝试报告数据的所有问题。 This is useful if you re-render the form, since then the errors can be put next to the corresponding field, and the user thus gets feedback on all the problems with the data, not the first one encountered by the form, since that could result in a lot of attempts to eventually fix the form.如果您重新呈现表单,这很有用,因为这样可以将错误放在相应字段旁边,因此用户可以获得有关数据的所有问题的反馈,而不是表单遇到的第一个问题,因为这可能导致许多尝试最终修复表单。

To summarize: there is a lot of logic in place in a Form to validate and clean data.总结一下: Form中有很多逻辑可以验证和清理数据。 Trying to implement that in a view is a popular mistake.试图在视图中实现这一点是一个普遍的错误。 It is cumbersome to do it correctly in a view, but it is also not very flexible: if you want to add an extra validator for a password for example, it will take a lot of work to implement that, especially if you want to that in multiple views.在视图中正确执行此操作很麻烦,但也不是很灵活:例如,如果您想为密码添加额外的验证器,则需要做很多工作才能实现,尤其是如果您想这样做在多个视图中。 Forms are created to work with reusable components like form fields , validators , uniqness checks, etc. It is also quite robust since it is aimed to validate request data that might be forged , and thus was not validated properly by the HTML attributes. Forms 被创建用于与表单字段验证器、唯一性检查等可重用组件一起使用。它也非常强大,因为它旨在验证可能被伪造的请求数据,因此没有被 HTML 属性正确验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM