This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker.

Sponsored

How to Use Forms in Django

June 21 2021 Yacine Rouizi
Form Django
How to Use Forms in Django

Overview

To be able to collect user input in a web application you need to use forms. Forms are a way to collect data from the browser and send it back to the server. The thing is, managing forms can be complicated: you need to render the form as HTML, submit it to the server, validate and clean up the form, communicate human-readable messages to inform the user if the form submission was successful or not, and finally save the data to the database and redirect the user to another page.

Luckily, Django provides a very rich and secure API to let you build forms to accept user input quite easily.

In this tutorial we are going to see how to create forms and how to use them in a view to handle the data sent by users from the client side.

Download the project

To be able to follow this tutorial, clone my repository on GitHub and install the dependencies by running the commands below:

git clone https://github.com/Rouizi/dj-forms.git
cd dj-forms
git checkout 322ed9fed36529979c7e0dbf8c8e46e16a8c23a9

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Sponsored

Create a Form

A form is a class inheriting from the parent class Form provided by Django, and its attributes represent the form fields.

Let's add a basic form inside the forms.py file:

# core/forms.py
from django import forms

class PostForm(forms.Form):
    title = forms.CharField()
    content = forms.CharField(widget=forms.Textarea, label="Content of the post")
    activate = forms.BooleanField(required=False)
    author = forms.CharField(max_length=255)
    email = forms.EmailField(required=False, help_text="Add your email if want it to be displayed (Not required).")

    def __str__(self):
        return self.title

I tried to create an example with multiple fields to see how each works.

Unlike models that can have a TextFIeld field, with forms we have only the CharField field when we want to collect text. But some text fields need to be bigger than others, like the content field.

To be able to customize a field, we can use the widget class. All fields have a default widget class, that corresponds to an HTML form widget such as <input type="text">. In our case, we used the forms.Textarea to have a <Textarea> widget.

We also defined a label argument in the content field which will change the <label> of the field.

The activate field is set to BooleanField, which by default uses the widget CheckboxInput, collects a boolean value. And we used the attribute required=False which makes this field not mandatory.

The max_length ensures that the author  field is at most 255 character.

Finally, we used the EmailField to ensure that the user has sent a correct e-mail address and the help_text attribute to add a helper text with the field.

Of course, there are many other types of form fields. Check out the documentation for the full list.

You can see in the image below what will look like the form that we created:

Simple Form

We can also add some styling to the Textarea field to change its dimension or background color as below:

content = forms.CharField(widget=forms.Textarea(attrs={'rows': 15, 'style': 'background-color: red;'}),
                              label="Content of the post")

And here is the result:

Styling the Form

 

Sponsored

Form in a View

Now let's see how to use our form in a view. A view needs to know which request is sent to the server in order to know what to do with the form.

If it receives a GET request it should return the default form (a blank form). But if it receives a POST request it should either re-render the form with error messages if it was not valid to inform the user what to do, or create a new entry in the database and return an HTTP redirect to the browser if the form is valid.

Below you can see how to do it:

# core/views.py
from django.shortcuts import render, redirect

from .forms import PostForm
from .models import Post


def post(request):
    # if this is a POST request then process the data
    if request.method == 'POST':
        # create and populate a form instance with the data coming for the POST request
        form = PostForm(request.POST)
        # The `is_valid` method returns True if there is data 
        # in the form and the form contains no errors 
        if form.is_valid():
            # create a post instance
            post = Post()
            # We get the data from the `cleaned_data` attribute,
            # write it to the `Post` model, and save
            post.title = form.cleaned_data['title']
            post.content = form.cleaned_data['content']
            post.activate = form.cleaned_data['activate']
            post.author = form.cleaned_data['author']
            post.email = form.cleaned_data['email']
            post.save()
            
            # redirect to the home page
            return redirect('home')
        
    # if this is a GET or other request create a blank form
    else:
        form = PostForm()
    
    # We render the post page to create a post or
    # to correct errors if there are any
    return render(request, 'post.html', {'form': form})

We first start by importing our form and model and the redirect function.

Then in the view, we check if this is a POST or a GET request. If this is a GET request, we create a blank form (we are in the else clause) then we call the render() method passing in the request, the HTML page and the form.

However, if the form is submitted using a POST request, then the view will create the form and populate it with data from the request.

Next, we check if the form is valid using the is_valid() method. If not, we return to the template with the previous data and the error messages.

If the form is valid, then a new attribute is created that contains the validated data: cleaned_data. Finally, we use this data to create a new post in the database and redirect the user to the home page.

On the template side, we don't have too much work because Django’s template language will automatically generate the HTML code for us. So copy the code below to the post.html file:

<!-- templates/post.html -->
{% extends 'home.html' %}

{% block content %}
<form class="mt-5 pt-5 ml-5 pl-5" method="post" action=''>
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Create</button>
</form>
{% endblock %}

We first declare the <form> and use the <form>’s action attribute to specify to which URL the data should be sent to. By using an empty string we tell the browser to send the data back to the current page URL.

Every form that uses a POST request (method="post") needs to use the {% csrf_token %} tag to prevent Cross Site Request Forgery attacks.

Finally, we use the {{ form.as_p }} template variable, which was sent by the view (return render(request, 'post.html', {'form': form})), to generate the HTML code for the form fields wrapped in <p> tags (.as_p).

Conclusion

In this tutorial we saw how to use the tools provided by Django to create forms. We also saw how to use them in a view in order to validate their data and to render them in a template.

I hope you enjoyed reading this article and if you have any questions don't hesitate to ask.

You can find the final code on GitHub at: https://github.com/Rouizi/dj-forms

Previous Article
Django Pagination With Class Based View

Django Pagination With Class Based View

Next Article
Django blog tutorial part 7: Serving Media Files From Amazon S3

Django blog tutorial part 7: Serving Media Files From Amazon S3

Subscribe

Join the mailing list to be notified about new posts and updates.

Leave a comment

(Your email address will not be published)