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.
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. 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.
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. The Django form will thus check for all fields that are required, if the value appears in request.POST and request.FILES.
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. 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. 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.
Cleaning does not only map strings on corresponding Python objects, it can also do some (small) post-processing on these fields. 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. 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. 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. 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. 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. For example for a CharField, if you pass a value for the min_length=… and/or max_length=… validators, it will thus check these. It will add all ValidationErrors 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. 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. One can however further add additional cleaning and validation to the 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. 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. 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.
After that, the form will call the .clean() method [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. 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.
For a ModelForm [Django-doc], the validation is not over yet. Indeed, the model itself can still have some validation. 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. 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. 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. 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. 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.
I've a source field:
source = SelectField("Source", choices=[
('option1', 'option1'),
('option2', 'option2'),
('option3', 'option3'),
validators=[InputRequired()])
Then an uri field which requires a different regex based on the above:
uri = StringField('URI', Regexp(regex=r'regex1'))
Eg. if option1 is selected regex will be regex1, if option2 regex2, and so on.
What would be the proper way to implement it with WTForms?
This functionality doesn't exist in WTForms. You'll have to tool this yourself. This quickly gets nontrivial, depending on your specific application logic/needs.
One way would be to have client-side JS send requests to a view that dynamically generates a new form, adding on the subsequent sections of the form based on inputs. For example, your fields could have an onChange or onBlur function that sends the inputs to a view that returns a new form with the next set of fields added on.
Another way to go about this would be with some clever form rendering, CSS and JS. For example, the form would be rendered with all possible fields, but the fields will be hidden and revealed conditionally based on previous selections through via JS/CSS. One concern with this method is that validation becomes complicated.
There are a few writeups out there on how this is accomplished with Django Forms, but not WTForms. Though, the same concepts should be readily applicable to WTForms.
Related docs: dynamic form composition.
I'm a newbie and right now I'm using Django forms to show some fields. One of these fields is a ModelChoiceField this show correctly model data, but I don´t know how I can fill a CharField later of select a option in the ModelChoiceField.
How I can make send the value of option selected for obtain the data that i need for later show this in a CharField, this is possible make directly from a djangoForm or do I need a new view to return the value?
There are two ways to achieve what you want I think:
Provide an initial value for your form value.
Bind your form to some data.
See this related stack overflow to provide initial values.
See Django's documentation on forms for binding data. There are two kinds of form states: bound and unbound. To create a bound form, you just need to create an instance of your form with some data: MyForm({'data-key1': 'data-value1', ...}).
I need to display two forms depending on the context.
The second form should contain a name and email text input followed by the first form content in that order, but only when the user is not authenticated.
I tried with Python class inheritance but in every tested cases the two new fields were displayed after the content of the first form.
Is there a way to correcly factorise common fields in deform forms or to specify a different display order?
The solution is probably to define the schema imperatively:
http://docs.pylonsproject.org/projects/colander/en/latest/basics.html#defining-a-schema-imperatively
This question is somewhat linked to a question I asked previously:
Generating and submitting a dynamic number of objects in a form with Django
I'm wondering, if I've got separate default values for each form within a formset, am I able to pre-populate the fields? For instance, a form requiring extra customer information to be pre-populated with the users names? In cases like adding an email field to an already existing table, and updating many of them at once.
Does Django provide an easy way to do this?
Pass in a list of dicts which contain the default values you want to set for each form:
http://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset