'Is it possible to use/test a value of Django's BooleanField without a model?
I'm trying to make a workflow where the user enters data on one page, then has to check the data and tick a tickbox to accept the T&C's. So the code has to check that the checkbox is checked before going on, but doesn't care until the second step.
It's not a bound field and I think that's the problem - I don't need a model just to handle a workflow, and I don't want to have to store, in a database, a simple ephemeral field in a form!
I'm running Django 2.1.5.
I've tried every possible combination of:
test_form.fields['tickbox'].value
- doesn't exist, which is ridiculoustest_form.fields['tickbox'] == False
- value doesn't change at allrequest.POST['tickbox']
seems to go missing?
views.py
from django.http import HttpResponse
from django.template import loader
from django.forms import Form, CharField, BooleanField
class test_form(Form):
name = CharField()
tickbox = BooleanField(required=False, initial=False)
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
if testform.fields['tickbox'] == True:
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = { 'testform : userform,
}
return HttpResponse(template.render(context, request))
I should be able to test the value of the field and get a changing response depending on if the user has ticked the box or not - I seem to get True
regardless?
Solution 1:[1]
Here is a way how to solve your issue using Class Based Views
and Function Based Views
:
So, first:
forms.py:
from django import forms
class CheckboxForm(forms.Form):
name = forms.CharField()
tickbox = forms.BooleanField(required=False, initial=False)
def clean_tickbox(self):
'''Here we can check if the checkbox is checked or not'''
tickbox = self.cleaned_data.get('tickbox')
if not tickbox:
# Raise an error if the checkbox is not checked
raise forms.ValidationError("You must select this option")
# And return the value
return tickbox
With a class based view:
views.py:
from django.views import View
from django.contrib import messages
class CheckboxView(View):
template_name = 'checkbox.html'
form_class = forms.CheckboxForm
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
# check if the form is valid
if form.is_valid():
# Use Django builtin messages framework
messages.success(request, "Checked!")
else:
messages.error(request, "not checked!")
return render(request, self.template_name, {'form': form})
With function based views:
from django.contrib import messages
def checkbox_func(request, *args, **kwargs):
template = 'checkbox.html'
if request.method == 'POST':
form = forms.CheckboxForm(request.POST)
# Check if the form is valid
if form.is_valid():
messages.success(request, "Checked!")
else:
messages.error(request, "Not checked!")
else:
form = forms.CheckboxForm()
return render(request, template, {'form': form})
urls.py:
from django.urls import path
from YOUR_APP import views
urlpatterns = [
# ... Your URLS
# Class Based Views
path('checkbox/', views.CheckboxView.as_view(), name="checkbox"),
# Function Based Views
path('checkbox2/', views.checkbox_func, name="checkbox_v2")
]
And your template: checkbox.html
:
{% for message in messages %}
{{message}}
{% endfor %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Demo:
Solution 2:[2]
First of all, yes it is perfectly possible to have FormField
s without them being declared in a Model
.
You seem to be trying to do form validation on your own when django already handles simple cases like this for you. Let's start by looking at the documentation of BooleanField
:
- Validates that the value is True (e.g. the check box is checked) if the field has required=True
Since that is exactly what you want to validate we can change the field definition:
tickbox = BooleanField(required=True, initial=False)
Since the documentation told us that django takes care of validating that the checkbox is actually checked there is no need for the custom validation code anymore. Let's look at the view next and refactor it:
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
# check if the form is valid (that includes the checkbox being checked)
if testform.is_valid():
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = {'testform': userform} # added a closing single tick
return HttpResponse(template.render(context, request))
So instead of doing custom validation you just call the .is_valid()
method of your Form
instance to run validation. If you want to access any of the fields instead of using testform.fields[fieldname]
you'd do testform.cleaned_data[fieldname]
which only accesses fields that have been validated.
For more information on form processing in general I highly recommend reading through django's Working with forms.
Solution 3:[3]
I simply use the "cleaned_data" to check if the field is not part of the model but its just a form field.
so in your case this will be in your view
if testform.cleaned_data['tickbox'] == True:
do_things()
else:
dont_do_things()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Chiheb Nexus |
Solution 2 | Fynn Becker |
Solution 3 | Vivek Amirthakadeswaran |