2

learning django, and trying to make a todo list.
A task is created first with only a task.name. Then I go to a taskdetail.html, with a form for task.detail, task.duedate, and task.done. The latter is a boolean that is true if the task is completed. I have the following in my template:

<input type="hidden" name="done" value=0 /> <input type="checkbox" name="done" value=1 {% if task.done %} checked {% endif %}>

In my views.py, I have:

def taskdetail(request, task_id): task = Task.objects.get(pk=task_id) if request.method == 'POST': form = DetailTaskForm(request.POST) if form.is_valid(): task.name = form.cleaned_data["name"] task.description = form.cleaned_data["description"] task.done = form.cleaned_data["done"] task.duedate = form.cleaned_data["duedate"] task.save() ... 

Strange enough, task.done alsways ends up true. It's default is false, and I have verified that it is indeed false before task.done = form.cleaned_data["done"]

I read that somewhere that value=0 is the same as false, but that doesn't seem to work for me. I also tried

<input type="hidden" name="done" value="" /> 

but then my form.is_valid returns false.

What could be the problem here? (I am working with Django 2.1 and python 3.7)

EDIT1: Willem's answer put me on track, but my problem isn't completely solved yet. I have now set task.done default to False, and made it not a required field. I changed my template to:

<input type="hidden" name="done" value="" /> <input type="checkbox" name="done" value=1 {% if task.done %} checked {% endif %}> {% if task.done %} <input type="hidden" name="done" value="on" /> {% endif %} 

the {{task.done}} that I send to the form is False, and I don't see how it can be manipulated and set to True in the form. (only after POSTing) So instead of checking if task.done == True, I should be able to check if the checkbox has been ticked.

1
  • 1
    The idea of a checkbox is that it is checked if it has a value, and false if it is missing in the post request.. Commented Oct 21, 2018 at 18:08

2 Answers 2

2

A checkbox is considered "checked" if it is part of the POST data, and unchecked if it is not in the POST data, as is specified in the Forms section of the W3 recommendations:

checkboxes

Checkboxes (and radio buttons) are on/off switches that may be toggled by the user. A switch is "on" when the control element's checked attribute is set. When a form is submitted, only "on" checkbox controls can become successful.

You thus can use the above "trick" by not rendering the field in case the task is not done, like:

{% if task.done %} <input type="hidden" name="done" value="on" /> {% endif %}
Sign up to request clarification or add additional context in comments.

3 Comments

@PeterM.: well a required=True check, then this means the checkbox must be checked, so this is probably indeed something you do not want: stackoverflow.com/questions/16988127/…
Indeed. See my EDIT. The user should have the choice to check it or not, and the result of that check should then alter Task.done to True or leave it to it's default False
@PeterM.: ah in that case you can make two <input> fields, one checkbox (done), and a hidden (old_done). But why don't you fetch the "old done" from the database?
0

The problem was solved with following code:

in forms.py, added required=False for done

class DetailTaskForm(TaskForm): description = forms.CharField(max_length = 600) done = forms.BooleanField(initial=False, required=False) duedate = forms.DateField() 

In my template: the value of "done" was set to "" by default, so that nothing was posted. Only when the checkbox was checked, done gets a value (in this case "on" but any value will do. Thanks Willem for putting me on track

<input type="hidden" name="done" value="" /> <input type="checkbox" name="done" value="on" {% if task.done %} checked {% endif %}> {% if task.done %} <input type="hidden" name="done" value="on" /> {% endif %} 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.