Using Django Form Fields, Widgets, and Attributes

Aug. 19, 2020, 11:09 a.m.

Django Beginners · 7 min read

Using Django Form Fields, Widgets, and Attributes

When creating a form using Django, form fields are an essential part of creating the Django Form class. There are over 23 built-in field classes with build-in validations and clean()  methods.

We will cover commonly used form fields along with form widgets to quickly get you on your way to creating forms for any site.

 

To get started

env > mysite > main > (New File) forms.py 

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):

Create a new file called forms.py in your app directory. This is the same directory as models.py and views.py.

Import forms from django at the top of the file. Then define a form class below. In this case, the form is named ExampleForm.

 


 

Common Fields

Let's start with some common fields, all of which have built-in widgets. These built-in widgets represent HTML elements.

 

CharField()

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	name = forms.CharField()

CharField is a Django form field that takes in a text input. It has the default widget TextInput, the equivalent of rendering the HTML code <input type="text" ...>.

This field works well for collecting one line inputs such as name or address.

 

CharField() with Textarea widget

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	name = forms.CharField(widget=forms.Textarea)

If you are looking to add a multi-line input field to your form, add the Textarea widget to a CharField. The Textarea widget renders the field as <textarea>...</textarea>, a multi-line text input.

Create this multi-line text input if you are looking to have a comment or message field.

 

CharField() with Textarea widget attribute

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	name = forms.CharField(widget=forms.Textarea(attrs={'rows':8}))


Finally, if you wish to increase or decrease the height of the Textarea, specify the attribute 'rows' in the widget. Please note the default number of rows is 10.

 

EmailField()

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	email = forms.EmailField()

EmailField has the default widget of EmailInput and renders as <input type="email" ...> in plain HTML. This field also uses the built-in Django validation EmailValidator that requires an @ symbol within the input for it to be considered valid.

 

BooleanField()

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	agree = forms.BooleanField()

A BooleanField, as the name implies, takes in a boolean data type of either True or False. The default is false and renders an unclicked checkbox in the HTML template.

 

DateField()

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	date = forms.DateField()

DateField only accepts date formatted values such as 2020-07-30. The default widget is DateInput but it renders just like a CharField with <input type="text" ...>.

 

DateField() with NumberInput widget attribute

from django import forms
from django.forms.widgets import NumberInput

# Create your forms here.


class ExampleForm(forms.Form):
    birth_date = forms.DateField(widget=NumberInput(attrs={'type': 'date'}))

If you are looking to add a calendar, import NumberInput at the top of the file then add the NumberInput widget allow with the attribute type 'date'. This then renders the equivalent of the HTML calendar <input type="date"> in plain HTML. 

 

DateField() with SelectDateWidget widget

from django import forms


# Create your forms here.

BIRTH_YEAR_CHOICES = ['1980', '1981', '1982']

class ExampleForm(forms.Form):
        birth_year = forms.DateField(widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES))

Django also comes with the build-in SelectDateWidget which displays three drop-down menus for month, date, and year.

We will discuss more drop-down menus below.

 

DecimalField()

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	value = forms.DecimalField()

If you are looking to collect number value inputs, use a DecimalField. The default widget is NumberInput.

 


 

Core Arguments

Now on to the core arguments. These are non-specific arguments accepted by all fields.

 

required (Boolean)

email_address = forms.EmailField( 
    required = False,
)

The required argument determines if the fields are required for form submission. It is a boolean (true or false only) and creates the asterisk mark next to the field.

The argument is assigned to every field and is true by default. 

 

max_length

message = forms.CharField(
	max_length = 50,
)

A maximum character length is assigned to the user input using max_length. And minimum character length is assigned using min_length.

 

label (String)

email_address = forms.EmailField( 
    label="Please enter your email address",
)

Django creates the field label by taking the designated field name, changing underscores to spaces, and the first letter to uppercase.

If you wish to create a custom label of a field, add the label argument.

 

initial (String)

from django import forms

# Create your forms here.

class ExampleForm(forms.Form):
	first_name = forms.CharField(initial='Your name')

To add pre-loaded information to input, use the initial argument.

 

initial for DateField

from django import forms
import datetime

# Create your forms here.

class ExampleForm(forms.Form):
	day = forms.DateField(initial=datetime.date.today)

The initial argument works well for the DateField given that you can set the initial input as the current date by using the import datetime.

 


 

ChoiceField, MultipleChoiceField, ModelChoiceField, and ModelMultipleChoiceField

Django comes with built-in choice fields so the user does not have to enter any information, rather they will select from the predefined choices. 

 

ChoiceField()

from django import forms

# Create your forms here.


FAVORITE_COLORS_CHOICES = [
    ('blue', 'Blue'),
    ('green', 'Green'),
    ('black', 'Black'),
]

class ExampleForm(forms.Form):
    favorite_color = forms.ChoiceField(choices=FAVORITE_COLORS_CHOICES)

Use the Django ChoiceField to create a drop-down menu of choices. The choices argument and the options are specified in the field.

Each choice requires a key and a value, with the value being the option displayed to the user. To call an initial value, specify the name of the key of the value you wish to appear on the page load.

 

ChoiceField() with RadioSelect widget

from django import forms

# Create your forms here.

FAVORITE_COLORS_CHOICES = [
    ('blue', 'Blue'),
    ('green', 'Green'),
    ('black', 'Black'),
]

class ExampleForm(forms.Form):
    favorite_color = forms.ChoiceField(widget=forms.RadioSelect, choices=FAVORITE_COLORS_CHOICES)

If you wish to have a radio select option, add the widget RadioSelect to the ChoiceField. This creates a radio, or small circle, buttons that are filled in when selected.

 

MultipleChoiceField()

from django import forms


# Create your forms here.

FAVORITE_COLORS_CHOICES = [
    ('blue', 'Blue'),
    ('green', 'Green'),
    ('black', 'Black'),
]

class ExampleForm(forms.Form):
    favorite_colors = forms.MultipleChoiceField(choices=FAVORITE_COLORS_CHOICES)

If you wish for the user to select multiple, use the MultipleChoiceField. 

 

MultipleChoiceField() with CheckboxSelectMultiple widget

from django import forms


# Create your forms here.

FAVORITE_COLORS_CHOICES = [
    ('blue', 'Blue'),
    ('green', 'Green'),
    ('black', 'Black'),
]

class ExampleForm(forms.Form):
    favorite_colors = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,choices=FAVORITE_COLORS_CHOICES,)

You can also add the widget CheckboxSelectMutiple to have the choices render next to checkboxes. 

 

ModelChoiceField()

from django import forms
from .models import MyModel

# Create your forms here.

class ExampleForm(forms.Form):
    model_choice = forms.ModelChoiceField(
        queryset = MyModel.objects.all(),
        initial = 0
        )

If you wish to connect a Django model to the form, import the model from the models.py file and use the ModelChoiceField and specify the queryset in the form field.

Set the initial to 0 if you wish for the first model object to be the initial value of the drop-down menu. 

For more information on creating a model, visit the article How to use Django Models.

 

ModelMultipleChoiceField() with CheckboxSelectMultiple widget

from django import forms
from .models import MyModel

# Create your forms here.

class ExampleForm(forms.Form):
    model_choices = forms.ModelMultipleChoiceField(
        widget = forms.CheckboxSelectMultiple,
        queryset = MyModel.objects.all(),
        initial = 0
        )

To allow for multiple-choice selection, use ModelMultipleChoiceField. If you wish to change the drop-down menu to checkboxes, add the widget CheckboxSelectMultiple. 

 


 

Rendering forms in templates

env > mysite > main > views.py

from django.shortcuts import render, redirect
from .forms import ExampleForm


# Create your views here.
def contact(request):
	form = ExampleForm()
	return render(request, "main/contact.html", {'form':form})

In views.py, import the form at the top of the file then add a contact function that specifies the form and the template. 

 

env > mysite > main > urls.py

from django.urls import path
from . import views

app_name = "main"

urlpatterns = [
    path("contact", views.contact, name="contact"),
]

Then add a URL pattern that connects the contact view to a URL path in the app's URL file.

 

env > mysite > main > templates > main  > contact.html

{% extends "main/header.html" %}

{% block content %}

{% load crispy_forms_tags %}

<div class="container py-5">
	<h3>Contact</h3>
	<form method="post">
    	{% csrf_token %}
        {{form|crispy}}
         <button class="btn btn-primary">Submit</button>
    </form>
</div>

{% endblock %}

Rending the form in the template only requires the variable {{form}}, the same context defined in the views function. However, the form example above also uses django-crispy forms with Bootstrap and the Django extends template tag.

 


 

Form submission

env > mysite > main > views.py

from django.shortcuts import render, redirect
from .forms import ExampleForm
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse


# Create your views here.
def contact(request):
	if request.method == 'POST':
		form = ExampleForm(request.POST)
		if form.is_valid():
			subject = "Contact" 
		    body = {
			'first_name': form.cleaned_data['first_name'], 
			'last_name': form.cleaned_data['last_name'], 
			'email': form.cleaned_data['email_address'], 
			'message':form.cleaned_data['message'], 
			}
			message = "\n".join(body.values())

			try:
				send_mail(subject, message, 'admin@example.com', ['admin@example.com']) 
			except BadHeaderError:
				return HttpResponse('Invalid header found.')
			return redirect ("main:homepage")
      
	form = ExampleForm()
	return render(request, "main/contact.html", {'form':form})

To submit the form, import send_mail, BadHeaderError, and HttpResponse at the top of the file. Then add two if/else statements that states if there is a POST request, and the form is valid, define the subject and message before trying to send an email to the specified email address in the send_mail function. 

 

env > mysite > main >settings.py

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Testing the form will require EMAIL_BACKEND to be added to settings.py.

For more information on setting up contact emails, visit the article Build a Django Contact Form with Email Backend.


0
Subscribe now

Subscribe to stay current on our latest articles and promos





Post a Comment
Join the community

1 Comments


Webdesign Aug. 20, 2020, 3:41 a.m.

Very interesting and it caught my attention. Bookmarking your article which will probably be my guide. Thank you very much. by cloudi5 https://www.cloudi5.com/website-design-company-in-coimbatore