What are they, and how to create a form with Django?

In this post we are going to create a form in Django, which is a fundamental element when we know how to take the first steps in Django, learn how to create a project, manage routes and take the first steps with our MTV; before we begin, let's talk about forms:

What is a Django form?

Django provides a Form class that is used to create HTML forms, or rather, their fields, since with them we can describe what the fields are, what type (integers, floats, text fields, lists...) and how it works and appears. It is similar to the ModelForm class that creates a form using the model, but does not require the model, therefore it is more manual and flexible than the latter.

What are forms used for in Django?

Forms are basically used to receive information from the user in some way and use that information for logical operations on databases. For example, registering a user taking as input her name, email, password, etc. Django maps the fields defined in Django forms to HTML input fields.

In such a way that with a single definition (Django forms) we have both the HTML rendering of the fields and the handling in the views/controllers and of course, validations on both sides.

How to create a form in Django?

The form data is stored in the file named as forms.py by convention, that is, the file can have any other name, but we usually call it as forms; this form is stored at the application level (within the application directory); therefore, each application can define its own forms according to the schema you want to give it.

How does Django submit form data?

In Django, the request object that is passed as a parameter to your view has an attribute called "method" where the request type is set and all data passed via POST can be accessed via the request in the form of a dictionary.

What is Django crispy forms?

This is also a common question, django-crispy-forms is nothing more than a filter | crispy and a {% crispy %} tag that will allow you to control the rendering behavior of your Django forms in a very elegant and DRY way. To have full control without writing custom form templates and with this, we can, for example, define classes that we want our form to have, for example, Bootstrap's or Tailwind's or our own.

Do I have to use Django forms?

Finally, the million dollar question; The recommendation is that you use Django's forms, as they are quite easy to use and handle all the validation for you (use required = True on each field, and you're all set for the simple 'not blank' check you mentioned), It is easy to obtain the data, clean it up, verify the status and you would lose ALL of this if we DON'T use them.

Create a form in Django

As we mentioned at the beginning of this block, we are going to create a form in Django, for that, as we mentioned, we create a file called forms.py in which we are going to define forms at the class level:

from django import forms
from .models import Category
class ProductsForm(forms.Form):
    title = forms.CharField(label="Nombre", required=True, max_length=255, min_length=3)
    description = forms.CharField(label="Descripción",widget=forms.Textarea(attrs={"rows":5, "cols":20}))
    price = forms.FloatField(required=True, min_value=0.1)
    category = forms.ModelChoiceField(label="Categoría", queryset=Category.objects.all())

Explanation of the above code

As you can see, by defining a class that inherits from forms.Form (where forms is a module that we import from Django) we can define a class based on form, where each property of the class is a form field... just like that simple.

Form fields

We have ALL kinds of fields, text type, numbers, selectable, files... in this case we are using some of the text type (title and description), one of the number type (price) and another of the selectable type, indicating a model (category )

  • In the same definition of the fields, we indicate some validations such as maximum, minimum size and if it is required.
  • We also indicate the label, therefore, with a single property, we can define both label and field.

We are going to create a create function, for the form, although you can perfectly adapt the form for the process of editing or updating records in Django:

def create(request):
    form = ProductsForm()
    return render(request, 'create.html', { 'form' : form })

As you can see, we create an instance of the form and pass it to a template:

Form rendering

To render it in a view/template, we can use the form that we pass as parameters from the views.py:

{% block content %}
 {{form}}    
{% endblock %}

Including asking for particular fields:

{{form.price}}

Or the Label

{{form.price.label}}

In case you want to build the fields one by one.

Conclusions

Forms are a mechanism that we have to work effectively with user data, we can use them for different purposes and Django gives us all the flexibility and simplicity that characterizes it to work with forms in an effective and extensible way.

Models for the forms

The models for the forms are classes that define the structure based on a Python class with its corresponding attributes; these classes allow:

  • Define the structure of the form.
  • Apply server-side and client-side validations.
  • Being able to reuse forms easily.

Case study

To use the forms, we can define them in a separate file at the application level; which by convention is called how forms.py.

With this in mind, let's create the following class:

comments/forms.py

from django.forms import ModelForm, Textarea

from .models import Comment

class CommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ('text',)

Explanation of the above code

ModelForm type forms offer us a simple scheme to define form fields; as you can see, it's a Python class that inherits from the aforementioned class.

Then, we have to define within this form class, a class called Meta, to define the structure of the forms; that is, to which models is this form related, and what are the fields; fields is nothing more than a python tuple.

These classes are very customizable and you can define saving processes, initialization at the class level, define attributes, customize form fields, validations, among others; although at the moment, we have a minimal example.

For model classes, it has been usual to create an instance and in this case, pass to the template.

Let's go to the add() function, and pass it as the second parameter, the form:

from .forms import CommentForm

    // ***
    form = CommentForm()
    return render(request,'comments/add.html',{'form':form})

From our template, we can print the complete form:

{{ form }}

And with this, all the fields that you have defined appear along with the LABEL:

ModelForm and template

Or by fields, independently:

{{ form.text }}

Use the one that seems best to you and suits you.

Process forms

From the request, we can obtain the data of the form that we are sending via POST or GET as we saw before; so, to establish the data that goes via POST in the previous form:

form = Form(request.POST)

We pass it as initialization to the form.

Case study

The add() function will look like this:

def add(request):

    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save()
    else:
        form = CommentForm()

    return render(request,'comments/add.html',{'form':form})

As you can see in the code above, from the same model, we can use the save() function to create a comment.

With this, you can perform some tests and send data from the template form:

ModelForm in the template with content

And you will see in your database:

List of records

If you put invalid data, that is, a form without values, you will see a client-side validation jump:

ModelForm in the template with content

- Andrés Cruz

En español
Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.