Django Form Fundamentals
Django forms inherit from forms.Form and serve two primary purposes: rendering form elements and validating submitted data. While they can handle rendering, their most common use case is data validation.
Without Django forms, you would need to manually write HTML like:
<form action="/submit-data/" method="post">
<label for="user_input">Enter name: </label>
<input id="user_input" type="text" name="user_name" value="{{ saved_name }}">
<input type="submit" value="Submit">
</form>Creating Form Classes
To leverage Django's form system, create a forms.py file in your app directory. This follows Django's convention pattern similar to models.py and views.py.
from django import forms
class UserInfoForm(forms.Form):
user_name = forms.CharField(label='Username', max_length=100)Key Points:
- Import the forms module from Django
- All form classes must extend
forms.Form - Each field type corresponds to an HTML form element (similar to Django models)
- The
labelparameter sets the field's label text max_lengthserves dual purposes: browser validation and server-side validation
Security Note: Browser-side validation can be bypassed. Always implement server-side validation as if the client is untrusted.
Each form instance has an is_valid() method for data validation. When valid, data is stored in the cleaned_data dictionary.
The above form renders as:
<label for="id_user_name">Username: </label>
<input id="id_user_name" type="text" name="user_name" maxlength="100" required>Note: Django forms don't include the <form> tag or submit button, giving you full control over the form structure and styling.
Field Types and Parameters
Common Field Types:
BooleanField: Renders as checkboxCharField: Text inputChoiceField: Select dropdownEmailField: Email inputURLField: URL inputDateField: Date pickerIntegerField: Number input
Field Parameters:
required: Defaults to True, makes field mandatorylabel: Text label for the fieldinitial: Default valuewidget: Customizes HTML renderingerror_messages: Custom error textdisabled: Disables the field when True
Widget Customization
Widgets control the HTML output:
# Basic usage
field = forms.CharField(
label="Username",
widget=forms.TextInput
)
# With HTML attributes
field = forms.CharField(
label="Username",
widget=forms.TextInput(
attrs={
"placeholder": "Enter username",
"class": "form-control"
}
)
)Available widgets include TextInput, PasswordInput, NumberInput, EmailInput, Textarea, CheckboxSelectMultiple, RadioSelect, Select, and others.
View Implementation
# views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import UserInfoForm
def process_user(request):
if request.method == 'POST':
form = UserInfoForm(request.POST)
if form.is_valid():
# Access validated data via form.cleaned_data
username = form.cleaned_data['user_name']
# Process data...
return HttpResponseRedirect('/success/')
else:
form = UserInfoForm()
return render(request, 'user_form.html', {'form': form})Implementation Notes:
- GET requests display an empty form
- POST requests validate submitted data
- Valid data proceeds with business logic
- Invalid data returns the form with error messages
- Use
form.is_boundto check if form has data
Template Rendering
<!-- user_form.html -->
<form action="/process-user/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>Template Requirements:
- Wrap Django form in your own
<form>tags - Include
{% csrf_token %}for POST forms - Manually add submit button
Advanced Rendering Options:
{{ form.as_table }}: Renders as table rows{{ form.as_p }}: Each field in paragraph tags{{ form.as_ul }}: Renders as list items
Note: You must provide the surrounding <table> or <ul> tags when using these methods.