I have a model, Task, with a “completed” field. It is a datetime field, so if it’s null/None then the task isn’t complete yet. (Previously, it was a Boolean field, but now I need the datetime information. I’ve migrated the development database successfully.)
class Task(models.Model):
...
completed = models.DateTimeField(
null=True, blank=True, default=False
)
...
My aim is that a user can check the box and submit the form with a post request and the current datetime is stored in the database.
The view is a generic class-based view (Update or Create):
class TaskUpdateView(UpdateView):
model = Task
queryset = Task.objects.prefetch_related(
Prefetch("notes", queryset=Note.objects.select_related("author").order_by("-created"))
)
form_class = TaskForm
template_name = "tasks/task_detail.html"
success_url = reverse_lazy("tasks:list")
I’m struggling with the form for this field. It’s a ModelForm, but with a checkbox widget for this field defined in the form’s Meta class.
class TaskForm(ModelForm):
...
class Meta:
model = Task
fields = ["completed", "text", "private", "deadline", "scheduled", "deleted"]
widgets = {
"completed": forms.CheckboxInput(attrs={
"class": "checkbox",
}
),
...
}
Unsurprisingly, trying to use this form, results in an attribute error - 'bool' object has no attribute 'strip'
, as Django attempts to clean the POST data submitted through the form and discovers it’s not quite as expected.
Traceback (most recent call last):
File "/Users/xxxx/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/views/generic/base.py", line 104, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/views/generic/base.py", line 143, in dispatch
return handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/views/generic/edit.py", line 182, in post
return super().post(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/views/generic/edit.py", line 150, in post
if form.is_valid():
^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/forms.py", line 197, in is_valid
return self.is_bound and not self.errors
^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/forms.py", line 192, in errors
self.full_clean()
^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/forms.py", line 325, in full_clean
self._clean_fields()
^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/forms.py", line 333, in _clean_fields
self.cleaned_data[name] = field._clean_bound_field(bf)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/fields.py", line 266, in _clean_bound_field
return self.clean(value)
^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/fields.py", line 204, in clean
value = self.to_python(value)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxxx/lib/python3.12/site-packages/django/forms/fields.py", line 550, in to_python
result = parse_datetime(value.strip())
^^^^^^^^^^^
Exception Type: AttributeError at /tasks/new/
Exception Value: 'bool' object has no attribute 'strip'
I have read through the form submission and validation process and how it is adapted for ModelForms.
With the helpful guidance I’ve received previously, I’ve delved into Classy CBV and I have tried overriding the clean_completed method in the form (which I’ve done for another field, successfully), I’ve tried overriding the post method and the form_valid method in the view; and I’ve tried overriding the clean method in the model. None has stopped the attribute error being raised in the same way as the traceback above.
What am I missing or any suggestions?
I’m wondering if I need to bite the bullet and separate the form from the model (ie not use a ModelForm), so that I can override the fields and the data cleaning?
I’m also toying with adding a boolean field back into the model and adding a whole separate datetime field, which would be a hidden field, and using the clean_completed method in the form to update the datetime field when the Boolean field changes to trueemphasized text.
Many thanks in advance
David