Decorating forms by django-crispy-forms Django 10.06.2016

Let's create a simple project from begining. First, create python3 virtual environment and install appropriate dependencies

# arch linux
yaourt -S python-pip python-virtualenv python-virtualenvwrapper

add environment variabel WORKON_HOME to shell

# vim ~/.zshrc

export WORKON_HOME=$HOME/.virtualenvs
source /usr/bin/virtualenvwrapper.sh

Re-open your console and create the WORKON_HOME folder

mkdir $WORKON_HOME

Create the virtual environment

mkvirtualenv -p /usr/bin/python3 sandbox

Install django

pip install django django-crispy-forms

Create directory for project and enter it

mkdir -p ~/projects/sandbox

Create django project

django-admin startproject sandbox

Create new app

python manage.py startapp movies

Add app to INSTALLED_APPS

INSTALLED_APPS = [
    'movies.apps.MoviesConfig',
    'crispy_forms',
    ...
]

Model

from django.db import models

class Movie(models.Model):
    title = models.CharField('Title', max_length=200)
    year = models.PositiveSmallIntegerField('Year')
    rating = models.FloatField('Rating', default=0)

    def __str__(self):
        return self.title

Form

from django import forms
from django.core.urlresolvers import reverse_lazy
from crispy_forms.helper import FormHelper
from crispy_forms import layout, bootstrap
from .models import Question, Movie

class MovieForm(forms.ModelForm):
    class Meta:
        model = Movie
        fields = ['title', 'year', 'rating']

    def __init__(self, *args, **kwargs):
        super(MovieForm, self).__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_action = reverse_lazy('movie_add')
        self.helper.form_method = "POST"

        self.helper.layout = layout.Layout(
            layout.Fieldset("Movie data",
                layout.Field("title"),
                layout.Field("year"),
                layout.Div(
                    bootstrap.PrependedText('rating',
                        """<span class="glyphicon glyphicon-thumbs-up"></span>""",
                        css_class="inputblock-level",
                        placeholder="Rating"
                    )
                ),
                bootstrap.FormActions(
                    layout.Submit("submit", "Save", css_class="btn-success"),
                )
            )
        )

View

from django.views import generic
from django.core.urlresolvers import reverse_lazy

from .models import Choice, Question, Movie
from .forms import MovieForm

class MovieListView(generic.ListView):
    template_name = 'movies/list.html'
    context_object_name = 'movies'
    model = Movie


class MovieAddView(generic.edit.FormView):
    template_name = 'movies/add.html'
    form_class = MovieForm
    success_url = reverse_lazy('movie_list')

    def form_valid(self, form):
        form.save()
        return super(MovieAddView, self).form_valid(form)                              

Templates: base.html, list.html, add.html.

Make the movies app modifiable in the admin

# vim movies/admin.py

from django.contrib import admin
from .models import Movie

admin.site.register(Movie)

Main urls.py

from django.conf.urls import url
from django.contrib import admin
from movies.views import MovieListView, MovieAddView

urlpatterns = [
    url(r'^$', MovieListView.as_view(), name='movie_list'),
    url(r'^add/$', MovieAddView.as_view(), name='movie_add'),
    url(r'^admin/', admin.site.urls),
]

Make migartion

python manage.py makemigrations movies

Migrate

python manage.py migrate

Create an admin user

python manage.py createsuperuser

Start the development server

python manage.py runserver

Result

django-crispy-forms

Useful links