I have a form that raises ValidationErrors for all fields if they are not valid. However, if there is no option from the ModelChoiceField selected, the form both doesn't submit (which is fine) and doesn't raise any ValidationError in the template either.
It seems that if request.method == 'POST': returns False if no category is selected on submit.
# Form
class PollersForm(forms.Form):
# Poller Category
poller_category = forms.ModelChoiceField(widget=forms.RadioSelect(attrs={
'class': 'poller-category-radio',
}), queryset=Category.objects.all().order_by('category'), label='Select a Category', required=True)
# View
def raise_poller(request):
"""
creates a new Poller object according to user inputs and redirects to it
"""
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = PollersForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the remaining data in form.cleaned_data as required
poller_category = form.cleaned_data['poller_category']
# Get the user
created_by = request.user
# Save the poller to the database
p = Poller(
poller_category=poller_category,
)
p.save()
# Get the created object and its id to redirect to the single poller view
created_poller = Poller.objects.get(created_by=created_by, id=p.pk)
created_poller_id = created_poller.pk
created_poller_slug = created_poller.slug
poller_url = '/poller/' + str(created_poller_id) + '/' + str(created_poller_slug)
# redirect to a new URL:
return redirect(poller_url, request, created_poller_id)
# if a GET (or any other method) we'll create a blank form
else:
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
<!-- Template -->
<form action="/raisepoller/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.errors }}
<!-- Poller Categories -->
<div class="fieldWrapper">
<div class="label">{{ form.poller_category.label_tag }}</div>
<div class="category-ctn">
{% for category in form.poller_category %}
<div class="category-wrapper">{{ category }}</div>
{% endfor %}
</div>
</div>
<!-- Submit Button -->
<button type="submit" value="Publish Poller" id="raise-poller-button">
<div class="button-wrapper">
<div class="button-icon"><img id="button-image" src="{% static 'images/send.png' %}"></div>
<div class="button-text">Publish Poller</div>
</div>
</button>
</form>
...which renders:
<div class="category-wrapper"><label for="id_poller_category_1"><input type="radio" name="poller_category" value="5" class="poller-category-radio" id="id_poller_category_1" required="">
Environment</label></div>
/* CSS */
.category-wrapper input {
position: fixed;
visibility: hidden;
}
.category-wrapper label {
display: inline-block;
background-color: #fdfdfd;
color: var(--main-darkblue-color);
padding: 0.2vw 0.5vw;
font-size: 1vw;
border: 2px solid #444;
border-radius: 4px;
margin-bottom: 0;
}
