This tutorial will help you perform form validation for your model fields. An example is provided which focuses on validating an Indian GST number and contact number using regex and validating the name by length only. For performing these validations we will be using utility functions and classes known as validators. The validators can be used both in form and model fields.
A validator is a callable object or function that takes a value and returns nothing if the value is valid or raises a ValidationError if not. These can be passed to a field’s constructor, via the field’s validators argument, or defined on the Field class itself with the default_validators attribute.
Django Documentation
Form validation is a crucial security feature that enables web applications to receive clean data. In most basic term, when data is entered by the user in the front-end and is subsequently sent to the back-end for storage and processing; we need to make sure that the data is received in the correct format. Validation helps us to achieve this objective. This tutorial assumes that you have some knowledge of how to build a basic Django CRUD application. If that is not the case, I would highly recommend this great AskPython tutorial. I have also explained about building RESTful API in my previous article which also discusses setting up a Django environment in Ubuntu. Make sure to check out those tutorials (if you need to) and then come back to this tutorial.
The tutorial is divided into seven small sections. Each section focuses on one tiny step at a time. This approach reduces the overall complexity of the entire tutorial and promotes ease of learning. The sections are mentioned below :
- Section A: Building an app and a model inside it
- Section B: Registering the model for the admin dashboard
- Section C: Adding form validation in the validation app
- Section D: Creating a view to add a new object to the model
- Section E: Creating HTML template for user input
- Section F: Creating a URL file for routes
- Section G: Testing Testing 🙂
Section A: Building an app and a model inside it
Say, we have a model called Company. The Company model has three fields which are name, gst_number and contact_number. We need to build a Company model class in the models.py file. But, first, let us create a new app called validation_app inside our project. Fire up your terminal and activate your project’s “virtualenv” and then run the following command.
django-admin startapp validation_app
Now, let navigate inside our validation_app and open its models.py file in any editor of our choice. The file should have the following lines :
# project/validations_app/models.py
# Ideally, we perform validation in the model too but for the sake of simplicity, we won't add any validation here.
from django.db import models
# Create your models here.
class Company(models.Model):
name = models.CharField(max_length=50)
gst_number = models.CharField(max_length=20)
contact_number = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "companies"
def __str__(self):
return self.name
Our Company class has three character fields namely name, gst_number and contact_number with a maximum length of 50, 20 and 15 respectively. We also defined a class Meta and set verbose_name_plural = “companies” this simply makes sure that in our admin panel the class is called companies in the plural and not companys. Also, the function __str__(self) will return the name of the object instead of the number whenever a new object is created.
We now need to migrate our model to the database. But, first make sure to add validation_app in your settings.py INSTALLED_APPS
#project/settings.py
INSTALLED_APPS = [
..........................,
..........................,
..........................,
..........................,
..........................,
..........................,
'validation_app',
]
Now, run migration commands at the main project folder inside your terminal.
python manage.py makemigrations
python manage.py migrate
Once the migration has completed successfully we can add the model in our admin dashboard to easily perform CRUD operations.
Section B: Registering the model for the admin dashboard
To perform CRUD operations first let us register the model to the admin dashboard. We simply need to add few lines in our validation_app/admin.py file :
#project/validation_app/admin.py
from django.contrib import admin
from .models import Company
# Register your models here.
@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
list_display = ("name","gst_number","contact_number")
The picture provided Fig 1. shows how the admin dashboard should look like after registration of the model in admin.py.
Section C: Adding form validation in the validation app
Once we can perform CRUD operations from the admin dashboard we can now start creating the form for our frontend. Inside the validation_app folder create a forms.py file.
touch forms.py
Once our forms.py file is created we can add the following contents in the validation_app/forms.py is given below :
# project/validation_app/forms.py
from django import forms
from .models import Company
from django.core.validators import RegexValidator
class CompanyForm(forms.ModelForm):
name = forms.CharField(min_length=5, max_length=50)
gst_number = forms.CharField(max_length=20, validators=[RegexValidator(
'\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1}', message="Enter a Valid Indian GST Number")])
contact_number = forms.CharField(max_length=15, validators=[RegexValidator(
'^(?:(?:\+|0{0,2})91(\s*[\ -]\s*)?|[0]?)?[789]\d{9}|(\d[ -]?){10}\d$', message="Enter a Valid Indian Phone Number")])
class Meta:
model = Company
fields = "__all__"
Here, in the name field, we have added a CharField with min_length as 5 and max_length as 50. This means that name could be any character with a minimum length of 5 characters and a maximum length of 50 characters.
The fields gst_number and contact_number has field named validators. It accepts a list where we are passing a method called RegexValidator. RegexValidator accepts the regex value as its first parameter and message as the second parameter. The message is simply the error message which is reverted back if the validation fails.
The regex expression for the validation of the GST number was taken from the answer of tk120404 in StackOverflow. Similarly, the contact number regex came from the answer of Vikas in StackOverflow.
Section D: Creating a view to add a new object to the model
Once our form is ready. We can now create a new method called add_new_company inside our validation_app/views.py file. This method will be used to add new objects inside the company Model. The views.py content is given below:
from django.shortcuts import render,redirect
from .forms import CompanyForm
from django.contrib import messages
# Create your views here.
def add_new_company(request):
if request.method == "POST":
form = CompanyForm(request.POST)
if form.is_valid():
try:
form.save()
messages.success(request, 'Company added Succesfully')
return redirect('add_new_company')
except Exception as e:
messages.error(request, str(e))
return redirect('add_new_company')
else:
form = CompanyForm()
return render(request, 'validation_app/company/add.html', {'form': form})
Our method first checks if it is receiving a POST request. For POST request we pass the data into our form named CompanyForm. Then a validation check is done with form.is_valid(). If the validation passes we save the form, else an error message is sent back. If the request is not a POST request an empty form is returned to the user template.
Section E: Creating HTML template for user input
The template for the HTML file is shown below. It is stored as add.html inside the path project/validation_app/templates/validation_app/company/. Comments are provided inside the HTML template for easier understanding.
<!-- project/validation_app/templates/validation_app/company/add.html -->
<!DOCTYPE html>
<html>
<head>
<title>
Add Company
</title>
</head>
<body>
<!-- Actual code for form starts here -->
<form method="POST" style="width: 50%;">
<!-- For error messages -->
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li {% if message.tags %} class=" {{ message.tags }} " {% endif %}> {{ message }} </li>
{% endfor %}
</ul>
{% endif %}
<!-- csrf token is mandatory and protects your application from cross site request forgery.-->
{% csrf_token %}
{{form}}
<button type="submit">Submit</button>
</form>
</body>
</html>
Section F: Creating a URL file for routes
Now, we just need to create a urls.py file inside our validation_app folder and add a path linking the URL to the view and include this urls.py file inside our projects main urls.py file. So let us first create the urls.py file of validation_app.
touch urls.py
Now, add the following lines in the urls.py file:
# project/validation_app/urls.py
from django.urls import path
from validation_app import views
urlpatterns = [
path('add_new_company/',views.add_new_company, name = "add_new_company"),
]
After this we will include the app’s urls.py in the project’s urls.py.
# project/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('validation_app.urls')),
]
Finally, we are good to go. Everything is done and we are ready to test it. But, wait !! First lets restart our project. If you are hosting it yourself in a Ubuntu server you can run sudo systemctl restart <service_name>, eg:
sudo systemctl restart my_project
Section G: Testing Testing 🙂
Now, all we have to do is some testing. Fire up you application and go to the the address http://yoururl.domain/add_new_company. For eg:
http://example.com/add_new_company
You can check your inserted value in your admin panel. With this basic example, you can just add new companies from the front end. In case you missed any step here is the Github Link.
I hope this tutorial helped you in some sense. If that is the case please make sure to comment below. Thank you for reading. Wish you happy coding 🙂
Md. Saifur Rahman is a Full Stack Django and Laravel Developer. Additionally, he loves to spend time learning and researching about the Internet of Things (IoT). He loves to share his work and contribute to helping fellow developers.