Web applications run on user interactions. Users enter data that is processed or stored and later displayed via web pages and views.
With Django, a crucial component of data collection is forms.
The methods and assets needed to generate a form are found in Django's FORM class, which is accessed by the import from django import forms
.
This guide will explore how to use forms in Django as a data capture tool. It assumes that you have at least beginner level knowledge in Django and a general understanding of the Django MVC. An introductory guide to Django can be found here.
Since forms are data entry components, they can be an entry point for malicious attacks, such as SQL injection and cross site request forgery. To prevent this, Django has some security checks, such as a CSRF token and checking form validity before saving. More about form security can be learned from the Django docs.
To better understand the use of forms, and specifically model forms in Django, consider a use case where your client wishes to build
an inventory management web app. Part of the scope is building a web form for capturing new inventory items
as well as a login form. Below is a snippet of the Inventory
model that influences how the inventory form is be designed.
1from django.db import models
2class Inventory(models.Model):
3 item = models.CharField(max_length=20)
4 item_code = models.IntegerField()
5 item_condition = models.CharField(max_length=50)
6 quantity = models.IntegerField()
7 def __str__(self):
8 return self.item
Model forms are components that are derived from an existing model. Simply, they are forms specifically for a model that you specify.
Generating a model form is quite easy. Below is a code snippet of one for the Inventory
model.
As best practice, forms in Django are defined in forms.py
.
1from django import forms
2
3from .models import Inventory
4
5class InventoryForm(forms.ModelForm):
6
7 class Meta:
8 # the model
9 model = Inventory
10 # the fields you want visible in the form
11 fields = ('item', 'item_code','item_description')
For the form to be visible to the user, you have to render it in an HTML file. This means you need both a view and an HTML file.
1from .forms import InventoryForm
2from django.shortcuts import render
3def new_inventory(request):
4 if request.method == "POST": # data was sent to server
5 form = InventoryForm(request.POST)# instantiate form object with data sent from user
6 if form.is_valid(): # no errors or missing values
7 form.save() # save form data to database
8 else: # normal get request
9 form = InventoryForm() # instantiate empty form
10
11 return render(request, 'inventoryapp/add_inventory.html', {'form': form})
The code block above renders a model form for the Inventory
model onto an HTML page.
Below is a snippet of an HTML file in which the form is rendered. The HTML file is referenced in the new_inventory
view as add_inventory.html
.
1{% extends 'myapp/base.html' %}
2
3{% block content %}
4 <h2>New inventory</h2>
5 <form method="POST" class="inventory-form">{% csrf_token %}
6 {{ form.as_p }}
7 <button type="submit" class="save btn btn-default">Save</button>
8 </form>
9{% endblock %}
This type of form does not serve a model. It is used to get information from the user and process it in one way or another. A common use case is a login form. It is not linked to a model, but you use the username and password to authenticate a user. Below are code snippets for how to set up a simple form
1from django import forms
2
3class LoginForm(forms.Form):
4 username = forms.CharField(label='Your name', max_length=100)
5 password = forms.PasswordInput()
1from django.http import HttpResponseRedirect
2from django.shortcuts import render
3
4from .forms import LoginForm
5
6def get_name(request):
7 if request.method == 'POST': # data was sent from user
8 # instantiate form object with data sent from user
9 form = LoginForm(request.POST)
10 if form.is_valid(): # no errors
11 # authenticate user and log them in
12 # redirect to dashboard:
13 return HttpResponseRedirect('/dashboard/')
14 else: # get request
15 form = LoginForm()
16
17 return render(request, 'login.html', {'form': form})
1<form action="/login/" method="post">
2 {% csrf_token %}
3 {{ form }}
4 <input type="submit" value="Submit">
5</form>
The basic forms rendered are not usually as appealing as one would wish. They need more work on styling. For this, third-party packages have been developed to style forms and give them a face lift. The most common are:
Mastery of form manipulation and associated methods gives you the power to design better and more efficient data collection techniques within a Django web app.
To further build on this guide and your knowledge of forms, follow this official guide to learn more about FormMixins, classes that provide methods and facilities for creating and displaying forms. They are most commonly used with Class-based Views (CBV).