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 Url
.
The previous week my UrlFrom
was derived from Form
and I had to create and save Url
object
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
derives from django.forms.ModelForm
instead of django.forms.Form
:
I added a Meta
class in which I defined that my UrlForm
is based on model Url
and
I listed fields which are used by this model.
After that it’s enough to use ModelForm
saving mechanism in view like this:
Usage of form.save()
does all the saving logic automatically. Data in form is stored as dictionary
in form.data
, so now it’s easy to access and I don’t have to extract it from self.request
anymore
to show message about successfully added url.
So adding url logic is much simplier, but what actually happen here?
More details about ModelForm
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
to Meta
class:
model
- it declares for which model you want to have fields generatedfields
list - if you want to have all fields simply:fields = '__all__'
, but it’s recommended to write them explicitly.
Minimal ModelForm
can look like this:
Main difference between ModelForm
and 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_messages
which is dictionary where keys are names of fields - excluded fields of model:
excluded
which should contain list of names of excluded fields - custom widgets defined by
widgets
which 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
labels
where keys are names of fields and values are labels - custom help texts for fields in dictionary
help_texts
where keys are names of fields and values are help texts - custom data types for fields in dictionary
field_classes
where 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
a method 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:
Leave a Comment