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 did mostly refactoring - I introduced Django Forms instead of rendering form by hand (it means I rewrote all logic for views). I added some Django library for managing bootstrap styles (actually picking one was really painful) - error management improved because of that. All my html templates are rewritten.
My github repo: firsor repo.
Currently successfully added url in my application looks like this:
Forms in Django
Usage of forms on web pages is so popular, that in Django there is a special mechanism for them.
It allows to add a form as a part of context to template - then render it automatically, so
a programmer doesn’t have to write a html code. To start with forms it’s necessary to create forms.py
file and create
a class which derives from django.forms.Form
. For a simple form without custom validation
it’s enough to create a form fields in this class, which correspond to fields desired in html form.
Here is an example of my form for urls:
Next in views.py
if you use method views you need to create an instance of this form and add it to view context.
Class views for forms I covered in later part of this post.
After that we can use this form in html templates in this way:
But there is one issue with that - this form again looks very bad… All my bootstrap styles at my form are gone!
Bootstraping Django Forms
There are a few solutions on how to style a form which was created using Django Forms mechanism.
Libraries
There are plenty libraries which can help with adding bootstrap to templates or forms:
- django-bootstrap3
- django-bootstrap-form
- django-forms-bootstrap
- django-crispy-forms
Actually it seems that names of these libraries were generated by some Django names generator. It’s hard to see a difference between django-bootstrap-form and django-forms-bootstrap… Unfortunately, I didn’t find forms-django-bootstrap - maybe I should write it myself.
These libraries are quite similar - they all add new custom bootstrap filters to templates.
All of them have to be loaded into template, for example:
{% load bootstrap3 %}
, to use form rendered with bootstrap styles:
{% bootstrap_form form %}
or
{{form | bootstrap }}
.
And for all of them it looks the same - it’s still the same bootstrap!
Anyway in my frisor project I decided to use django-bootstrap3, because this one is not
about forms only. Still the documentation of this framework sucks - for example they forgot to mention
that to use it, it should be put into settings.py
in INSTALLED_APPS
as bootstrap3
.
It’s really painful that there is no naming convention for Django packages and application names. Actually application name can be so different than package name - you are on your own there…
Styling in Django Forms class
It’s possible to put styles into forms class. For me it’s quite bad design, because a form should be just a model of data and it shouldn’t have anything to do with presentation of it. It’s the same as putting some business logic into ORM model class.
Anyway here is an example:
There is a possibility to add html attributes to widget field of model field constructor. Also there are other ways to achieve this: by using Meta class in form class. Meta classes deserve more attention, so I’ll leave them for feature posts.
Styling in html templates
There are two ways: writing own filter which will add a css class to a field or simply putting all necessary styles into html form by hand (it means you don’t have to add a form to context when rendering view). I’ll not cover them more - first is about custom filters in templates for what I want to write a separate post. Second way I’ve used previous week.
Class view and forms in Django
Actually I was a bit surprised that Django tutorial didn’t mention that it’s possible
to have a class views in views.py
. Actually I’ve read that views.py
with methods instead
of classes is quite bad design. So I refactored my views.py
to use class views - for a form for
Urls
I’ve a class UrlForm
which derives from django.views.generic.FormView
. I’ve implemented
two methods from it - get_context_data
is for managing context for all requests,
form_valid(form)
for managing request from form. My new views.py
looks like this:
Method form_valid
does the saving url logic as before I did in my index
method. Method
get_context_data
is responsible for getting all urls from database and put them into context to
render on my index.html
template.
To render an index.html
template properly you need to point to a class view using as_view
method:
In my views.py
there are messages - they allow to display error or success messages in a
nice way:
and they are shown like this:
My TODO list:
- Introduce unit tests.
- Add comments and tags to urls.
- Refactor database logic from
views.py
to use someservice.py
. - Fix issue with not cleared form after submit.
- Read about WebSockets to introduce chat mechanism.
Leave a Comment