Form in Django plays a key part in other components.
It glues the data from the web form to the database or other services.
It serves as the bridge between user input and the database or other services. A Django Form takes
user input from web forms, transforms it into Python objects, prepares the data for storage, and
saves it to the database. Conversely, forms can retrieve data from the database or
other services, converting Python objects back into HTML/HTTP for user interaction. Additionally,
Django Forms provide essential validation and error-handling mechanisms to ensure data integrity.
Forms are also responsible for rendering UI widgets that users interact with, Form is composed of
Fields and Field is composed Widget. Django Form allows theming to a certain extent. For
example, the Field attribute in the Python object maps to the HTML input attribute.
The HTTP protocol and web browsers emerged in the late 1980s, evolving substantially throughout the
1990s, and so today. During this era, web browsers were developed as tools for interaction with web servers.
Initially, browsers lacked JavaScript capabilities, and UI widgets were limited to basic HTML
elements such as input, select, and textarea. These components were fundamental for user interaction
with the web server.
Browsers have evolved, CSS styles, JavaScript, and AJAX have been introduced. These technologies have changed the landscape of web development. Django overall design is a multi-page web-app and the frontend web components are designed to be stateless.
Modern Frontend frameworks allow front-end developers to create more interactive UI widgets which are web components and stateful.
There is also another route in-between, Django + frameworkless frontend. This looks welcomed by a majority of Django developers.
With simple JS libraries like jQuery, HTMX, Alpine.js, Bootstrap CSS. Django developers can
create (I guess) 80% of the web frontend requirement with no steep learning obstacles.
It is crucial to understand that Django Forms are designed to handle HTTP web forms, which can be
viewed as a form of data serialization akin to JSON or XML. The web form format is well-defined
within the HTTP protocol, and Django Forms are specifically intended to work with
application/x-www-form-urlencoded data.
Web Forms are primarily meant for human input via web browsers, making them less suitable for data
exchanges between services. In scenarios requiring service integration and data exchange, REST APIs
utilizing JSON are the preferred method (Though there exist other alternatives like GraphQL).
Consequently, Django Forms cannot directly handle AJAX JSON requests. For applications with
extensive REST API usage, frameworks like Django REST Framework (DRF) and Django Ninja are
recommended.
In parallel, REST API layer works a similar role as Django Form. DRF emphasizes on the data serialization, validation, and rate limit too.
Form is a class inheriting form classes under "django.forms". Common examples include
django.forms.Form and django.forms.ModelForm. These classes define fields and widgets that represent
the form's structure and user interface:
from django import forms
class aForm(forms.Form):
aField = forms.DateField(hidden=True,widget=forms.HiddenInput)
bField = forms.CharField(max_length=100,widget=forms.Textarea)
def clean_aField(self):
data = self.cleaned_data['aField']
if data < datetime.date.today():
raise ValidationError(_('Invalid date'))
return data
Django Form basically is a Python class. There is a hierarchical structure of Django Form. Form, Field, and Widget are Python classes:
The above example demonstrates a basic form class aForm with two fields, aField and bField.
The aField is a DateField with a hidden widget, while bField is a CharField with a
Textarea widget. The clean_aField method is a validation method that checks if the date is
valid. If the date is invalid, a ValidationError is raised.
This short example showed that Form is responsible for playing the joint between web frontend and the data integrity. The validation is done by the Form class.
Model Form is a variant of Form that is designed to work with Django models easily plus a few more
features dealing with HTTP, Database API, and Validation. With Model Form, use META class to declare the
connections to the Model class. The form is then passed as context to the template.
# models.py:
class ProfileImage(models.Model):
pic = models.ImageField(upload_to="profilepics/") # a Model Field
owner = models.
OneToOneField(User, on_delete=models.CASCADE) # a Model Field
def __str__(self):
return self.owner.username + "-" + self.pic.name
# forms.py:
from .models import ProfileImage
class ProfileImageForm(forms.ModelForm):
# a Form Field mapping to the model field "pic"
pic = forms.ImageField(label="Profile Picture")
through_ajax = False # not a Field
ajx_upload_url = reverse_lazy("forms_upload") # not a Field
class Meta: # Python Meta class syntax
fields = ["pic"]
model = ProfileImage
The above example is mapping a Model Form to a Django Model "ProfileImage".
The Meta class has two attributes, fields and model. The fields attribute specifies the fields to
be included in the form, while the model attribute specifies the model to be used. The pic field
is an ImageField with a label "Profile Picture".
Data integrity is crucial for any web application. Inputting data without validation can lead to significant issues, making it essential to validate all user inputs. In most typical use cases, a Model Form serves as the primary interface for the CRUD (Create, Read, Update, Delete) operations associated with a model in the database.
A Model Form in Django is designed to facilitate seamless interaction with HTTP requests, templates, and Django models. It maintains several key internal states that enable it to function effectively, including:
A full example looks like:
# models.py:
from django.db import models
from django.core.exceptions import ValidationError
class ExampleModel(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
def clean(self):
# Custom validation logic for the entire model
if self.age < 0:
raise ValidationError("Age cannot be negative.")
def validate_constraints(self):
# Additional constraints can be validated here
if not self.name:
raise ValidationError("Name cannot be empty.")
# forms.py:
from django import forms
from .models import ExampleModel
class ExampleModelForm(forms.ModelForm):
class Meta:
model = ExampleModel
fields = ['name', 'age']
def clean(self):
# Call the parent class's clean method to ensure validation
cleaned_data = super().clean()
# Custom validation logic for the form
name = cleaned_data.get('name')
age = cleaned_data.get('age')
if age is not None and age < 0:
self.add_error('age', "Age cannot be negative.")
return cleaned_data
def clean_name(self):
# Specific field validation for the 'name' field
name = self.cleaned_data.get('name')
if not name:
raise forms.ValidationError("Name cannot be empty.")
return name
def clean_age(self):
# Specific field validation for the 'age' field
age = self.cleaned_data.get('age')
if age is not None and age < 0:
raise forms.ValidationError("Age cannot be negative.")
return age
# Usage Example
def save_example_model(form_data):
form = ExampleModelForm(form_data)
if form.is_valid():
example_model_instance = form.save(commit=False)
# some more processing
example_model_instance.save()
else:
print(form.errors) # Handle form errors
For more information, refer to Django Model Form validation
Django provides built-in validators as well as the capability to create custom validators, ensuring that data meets specific criteria before being processed or saved.
Form is just an abstract concept. By itself has no information about how it visually appears. As mentioned above, Form is composed fields and fields corresponds with web widgets.
There are CSS and JavaScript to style the form. Full-fledged form components take a significant amount of effort to design and implement. In the communities, Bootstrap is a popular CSS framework, and minimal JS libraries like jQuery, Alpine.js, and HTMX are popular too.
If using React.js, Django would be used as a REST API backend instead.
There are plenty of extensions that allow Django Form to work in more modern approaches.
Django Form is a tough topic to deal with.