In the earlier Django tutorial, I have explained- how to create a model, form, and template.
In this tutorial, we are going to learn how to create a Django form with a multi-choice field (multiple choice options) and select initial values by default.
Here is a short glimpse of the Django form we are going to create in this tutorial.
I will explain this with an example.
Follow the steps one by one.
Step 1: Create model with CharField()
We are going to create a model which has a field of type CharField
.
Update models.py
.
from django.db import models class Contact(models.Model): prefered_contact= models.CharField(max_length=120, choices=CONTACT_PREFERENCE, default='')
Step 2: Define Django Form
Create a Django form with the form field of type MultipleChoiceField.
Here choices are the options for the multi-select checkbox.
Update forms.py
.
CONTACT_PREFERENCE = [ ('email', 'Email'), ('chat', 'Chat'),' ('call', 'Call'), ] class ContactForm(forms.ModelForm): prefered_contact = forms.MultipleChoiceField( choices=CONTACT_PREFERENCE, widget=forms.CheckboxSelectMultiple() ) class Meta: model = Contact fields = ('prefered_contact',)
Step 3: Show Django Form in Template
You can use a Django template tag to display the HTML form.
{{ form.as_p }}
It will show the Django form with a multi-select checkbox. This is pretty easy.
Now, what happens when you submit the form?
When you submit the form, the values of the selected options are stored as a list of values. But, this list is saved in the model as a Python string. You can check that in the Django admin panel.
In this Django form, we want to show the default options selected.
In the above example, when the user opens the form, the ’email’ and ‘chat’ options should be selected by default.
Update the Django view by setting the initial values for the checkbox field while creating an instance of the Django form. The initial value to the multiple-choice fields should be the list of values.
def land_demand_form(request): form = ContactForm(request.POST or None, initial={"prefered_contact": ['email', 'chat']}) context= {'form': form}
Now, it will show the initial values (’email’ and ‘chat’) populated on the Django form.
Note: Property initial
works when you use the {{ form.as_p }}
template tag to create the Django form. If you are customizing a Django form template manually, this method does not work.
In that case, pass the list of the default selected options as a new context variable (says ‘selected_contact’) to the Django template.
This is a bit tricky.
def land_demand_form(request): form = ContactForm(request.POST or None) context= {'form': form, selected_contact=['email', 'chat']}
And update the Django template to show the multi-select checkbox options.
{% for value, text in form.prefered_contact.field.choices %} <label for="id_prefered_contact_{{ forloop.counter0 }}"> <input type="checkbox" name="prefered_contact" value="{{ value }}" id="id_prefered_contact_{{ forloop.counter0 }}" {% if value in selected_contact %} checked="checked"{% endif %}> {{ text }} </label> <br> {% endfor %}
You are done!
If you are allowing users to update or edit the form, fetch the object from the model (one that the user has already submitted). It will return the Python list of the earlier selected options.
Now, instead of hardcoding the initial (default) value, pass the list of selected options and populate them in the HTML form.
Update the Django view as follow.
import ast def land_demand_form(request): obj= get_object_or_404(Contact, user=request.user) res = ast.literal_eval(obj.prefered_contact) form = ContactForm(request.POST or None, initial={"prefered_contact": res}) context= {'form': form}
Here, obj.pregeted_contact
returns, the string representation of the list. We are using ast
module to convert the string representation of the Python list into the actual Python list.
With this, users can edit or modify the earlier selected options.
If you have any doubt, let me know in the comment section below.
Hi, Aniruddha,
It is good tutorial.
But, variable CONTACT_PREFERENCE doesn’t seem to defined in Contact model class
Hi Naveen,
Thanks for identifying this.
One can define CONTACT_PREFERENCE in the model itself. I prefer defining this type of variable inside config.py.