Contact Information

KodeBlog

We're Available 24/ 7. Drop us an email.

Django Form Processing

Forms allows us to get input from the users that we then submit to the backend server for processing. Forms are created using HTML mark up but Django provides us with special tools that simplify and automate the process.

In the last lesson, we created a login page and also logout link. Now, let's start to add create and update pages.

Topics to be covered

We will cover the following topics in this lesson

  • Form Processing Basics
  • Adding New Books
  • Django-widget-tweaks App
  • Update Existing Books
  • Displaying Edit Links
  • Lesson Challenge
  • Summary

Form Processing Basics

Basic knowledge of HTML forms is required for you to successfully complete this lesson so we will share the most important aspects in this section.

HTTP Verbs

HTTP verbs are used to specify the action to be taken when processing forms. We have the major four verbs GET, POST, PUT and DELETE which correspond to actions Read, Create, Update and Delete respectively. Web browsers support GET and POST verbs out of the box.

GET Verb

When working with GET, the form input is visible in the URL as query strings. This makes it good for actions like searching for authors and bookmarking the search results so that we can easily return to the page. You should only use GET when you want the form input to be visible in the URL

POST Verb

Forms that use the POST verb hide the form values in the background. This makes it great for actions like logging in the user because we do not want to display the username and password in the URL. Also like mentioned in the above section, whenever you want to create a new resource, you should use POST verb.

Form Action

The action attribute of the form is used to point it to the backend URL that is responsible for receiving input from the form and processing it.

HTML Form Syntax

The following code shows how to create a form using HTML

<form method="http_verb" action="url_to_backend">
    {% csrf_token %}
    <div class="form-group">
        ....
    </div>
    <input type="submit" class="btn btn-primary" value="Submit">
</form>

HERE,

  • <form method="http_verb" action="url_to_backend"> defines a form element and using attributes, we specify the method which is the HTTP Verb to be used. In our case, it can either be GET or POST.
  • {% csrf_token %} for security reasons, the seven lords of the inner council of Django by law demand that we provide a Cross site Request Forgery token so that our forms can be processed when working with POST verb. Absent that, we get an error message.
  • <div class="form-group">...</div> contains the markup for our form. We will shortly look at this in detail.
  • <input type="submit" class="btn btn-primary" value="Submit"> the input of type submit is used to submit the form to the backend for processing

Adding New Books

CreateView is a class that helps us to add a new object to our database. Since we want to limit it to only logged in users we use LoginRequiredMixin. LoginRequiredMixin checks if the user is authenticated and if he/she is not, redirects them to the login page and after a successful login redirects them to requested link:

from django.views.generic.edit import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin


class BookCreateView(LoginRequiredMixin, CreateView):
	login_url = '/auth/login'
	model = Book
	fields = ['title', 'author', 'description', 'category']
	template_name = 'books/create.html'

HERE,

  • login_url = '/auth/login' is the URL that the user will be redirected to login, if not logged in yet.
  • fields = ['title', 'author', 'description', 'category'] We define the fields of our model which will be in the form. Be careful about it, Do not miss any required field.
  • model = Book specifies the model name that we want to work with
  • template_name = 'books/create.html' sets the path and name of the template that contains our form for adding new books.

The HTML for books/create.html will be as follows

{% extends 'base.html' %}
{% block content %}
<div class="container col-md-6">
    <h3 class="mt-2">Add New Book</h3>
	<form method="post">
    {% csrf_token %}
	{{ form.as_p }}

	<inut type="submit" value="Submit">
	</form>
</div>
{% endblock %}

HERE,

  • {{ form.as_p }} puts the form items automatically

Loading the following URL into your browser

http://127.0.0.1:8000/books/create

Produces the following page

Django Form No Styling

As you see it does not have the style. We need to install an app that will allow us to add styling classes to form elements as they are been generated automatically for us.

Django-widget-tweaks App

We need to install django widget-tweaks app by running the following command

pip install django-widget-tweaks

And add it to our apps in settings:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'authors',
    'books',
    'categories',
    'django_seed',
    'widget_tweaks',
]

We can now modify our template as follows

{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
<div class="container col-md-6">
    <h3 class="mt-2">Add New Book</h3>
    <form method="post">{% csrf_token %}
        {% for field in form %}
        <div class="form-group">
            {{ field.errors }}
            {{ field.label_tag }} {{ field | add_class:"form-control" }}
        </div>
        {% endfor %}
        <input type="submit" class="btn btn-primary" value="Update Book">
    </form>
</div>
{% endblock %}

HERE,

  • {% load widget_tweaks %} loads the package. So we can use it.
  • {{ field | add_class:"form-control" }} we can use add_class from widget-tweaks, it adds class attribute to the field.

Save the changes and load the form again. You should be able to see the following beauty

Django Form with Styling

As you can see from the above image, the styles have been applied to our application using widgets-tweak

Update Existing Books

An update form is like a create form. Instead of CreateView, we need to use UpdateView and also we need a URL that has the pk in it. However, we can use the same form template file that we have used to Create Book.

class BookUpdateView(LoginRequiredMixin,UpdateView):
	login_url = '/auth/login'
	model = Book
	fields = ['title', 'author', 'description', 'category']
	template_name = 'books/update.html'

HERE,

  • The above code is similar to the one for create except we are using UpdateView and loading the template books/update.html

And in urls:

path('books/<int:pk>/edit', views.BookUpdateView.as_view()),

The template for books/update.html will be as follows

{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
<div class="container col-md-6">
    <h3 class="mt-2">Update Book</h3>
    <form method="post">{% csrf_token %}
        {% for field in form %}
        <div class="form-group">
            {{ field.errors }}
            {{ field.label_tag }} {{ field | add_class:"form-control" }}
        </div>
        {% endfor %}
        <input type="submit" class="btn btn-primary" value="Update Book">
    </form>
</div>
{% endblock %}

HERE,

  • The template code is the same as the one for create so.

Load the following URL into your web browser

http://127.0.0.1:8000/books/3/edit

You should be able to get results similar to the following

Django Forms Update

As you can see from the above results, our form has populated our form with book details that match the primary key of 3. You can make changes and click on Update Book button, you should be able to see the changes.

Displaying Edit Links

We will now modify the books/list.html template so that if a user is logged in, they should be able to see the Edit Book link. If the user is not logged in, then we will not display the edit link.

Open books/listing.html and update the code as follows

{% extends "base.html" %}

{% block content %}
<div class="row">
    <h3 class="mt-2">{{title}}</h3>
    <table class="table">
        <thead>
            <tr>
                <th scope="col">Title</th>
                <th scope="col">Author</th>
                {% if user.is_authenticated %}
                    <th scope="col">Edit</th>
                {% endif %}
            </tr>
        </thead>
        <tbody>
            {% for book in object_list %}
            <tr>
                <th scope="row"><a href="{% url 'books.show' pk=book.id %}">{{book.title}}</a></th>
                <td><a href="{% url 'authors.show' pk=book.author.id %}">{{book.author}}</a></td>
                {% if user.is_authenticated %}
                    <td><a href="{% url 'books.edit' pk=book.id %}">Edit Book</a></td>
                {% endif %}
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
{% endblock %}

HERE,

  • {% if user.is_authenticated %}...{% endif %} uses the if statement to check if the user is logged in to create a column Edit with its corresponding row that contains a hyperlink to the edit page.

Load the following URL into your web browser

ddd

You should be able to see the following page

Books Edit Links

Lesson Challenge

Following the examples laid down in the sections on books, create add and update templates with all the necessary URLs and Class Views for Authors and Categories applications.

Happy coding!

Summary

Forms are used to capture input from the users and submit it to the backend for processing. HTTP verbs are used to specify the processing action and how the browser should handle form data. GET verb makes form parameters visible in the URL while POST verb submits the data to the backend without displaying them in the URL. All forms with POST method must include a csrf token for security reasons. The app django-widget-tweaks is used to add styling to form elements as they are been created automatically.

Author: Rodrick Kazembe

Rodrick is a developer who works on Desktop, Web and Mobile Applications. He is familiar with Python, Java, JavaScript, C++, C#, Kotlin, PHP, Python and the list goes on. Rodrick enjoys sharing knowledge especially when it comes to technology.

Django Authentication

Django Ajax

Leave A Reply