This week I had some fun with with forms in Django in my application frisor. Here is a post about my progress and issues I’ve encountered.
Quick reminder what is frisor
Frisor is a web application in Python/Django which is just a box for interesting urls. When using untrusted network I don’t want to login anywhere to save interesting content I found. More about this is here: Introduction to frisor.
This week I started to introduce tags for my urls. As I didn’t want to reinvent a wheel again, I decided to use some Django library for tagging, but it’s a topic for a different story. Also I did small fixes:
- after url submit form is cleared
- refactored saving data sent by url form
- changed in my template: url list is now below url form
- introduced tests
My project on github: firsor repo.
Currently my application looks like this:
Form for model in Django
I wanted to have an auto-generated form for my model
The previous week my
UrlFrom was derived from
Form and I had to create and save
manually. My form was really simple:
After POST request I had to extract all request data, create
Url object instance with this data,
and finally save
Url object in database like this in my view:
But it happens that my form is based on a single model (
Url) and there is a
mechanism to tell Django to save model object automatically. Actually it’s possible
to have a form which is able to handle more complicated models with foreign keys -
in documentation there are described mappings between model and form fields.
Here is my form which
django.forms.ModelForm instead of
I added a
Meta class in which I defined that my
UrlForm is based on model
I listed fields which are used by this model.
After that it’s enough to use
ModelForm saving mechanism in view like this:
form.save() does all the saving logic automatically. Data in form is stored as dictionary
form.data, so now it’s easy to access and I don’t have to extract it from
to show message about successfully added url.
So adding url logic is much simplier, but what actually happen here?
More details about
ModelForm is a
Form which has a mechanism for automatic generation of certain fields in
model. It generates template data (so HTML code for inputs for example)
based on information from its
Meta class. For minimal configuration you need to add
model- it declares for which model you want to have fields generated
fieldslist - if you want to have all fields simply:
fields = '__all__', but it’s recommended to write them explicitly.
ModelForm can look like this:
Main difference between
Form is that it performs two validations:
- form validation
- model instance validation
instead of only form validation.
Another difference is that in
ModelForm there is
save method introduced for saving
an instance of an object in database. It performs validations mentioned above if there were
not performed earlier.
Customized Meta class in ModelForm
Meta class of
ModelForm can contain:
- custom error messages:
error_messageswhich is dictionary where keys are names of fields
- excluded fields of model:
excludedwhich should contain list of names of excluded fields
- custom widgets defined by
widgetswhich is dictionary where keys are names of fields and values are widgets which should be used for those fields
- custom labels for fields in dictionary
labelswhere keys are names of fields and values are labels
- custom help texts for fields in dictionary
help_textswhere keys are names of fields and values are help texts
- custom data types for fields in dictionary
field_classeswhere keys are names of fields and values are types (class names)
Clearing form after submit
Last week I had an issue that my form wasn’t cleared after submission. My mistake was that in
my view in method
form_valid which is run after POST request I used
django.shortcuts.render for rendering view after form submit.
Better approach here is to use
django.shortcuts.redirect, because after saving a data from
form, my view should be refreshed to load urls data using
self.get_context_data. It resolved
an issue with not cleared form after submit: