[Django] #27370: Django's Select widget adds a required="required" attribute, even if created with empty_label=True

17 views
Skip to first unread message

Django

unread,
Oct 20, 2016, 3:34:14 PM10/20/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------+-------------------------------------------------
Reporter: | Owner: nobody
alexpirine |
Type: Bug | Status: new
Component: Forms | Version: 1.10
Severity: Normal | Keywords: HTML,Select,wdiget,ModelChoiceField
Triage Stage: | Has patch: 0
Unreviewed |
Easy pickings: 0 | UI/UX: 0
-------------------------+-------------------------------------------------
I didn't think it was wrong in HTML, but the W3C validator says so, and
after reading this discussions, it seems to be right:

https://github.com/validator/validator/issues/47

This is how I could explain it:

If a form field is required and has the `empty_label=True` argument, the
generated `<select>` will have a `required="required"` attribute. This
doesn't make sense since the first item will be selected anyways, and
there is no way for the user to ''unselect'' a value.

So, the `required="required"` attribute is useless.

Example:

{{{#!python
class TestForm(forms.Form):
some_field = forms.ModelChoiceField(queryset=SomeModel.objects.all(),
empty_label=None)
}}}

results in:

{{{#!text/html
<select id="id_some_field" name="some_field" required>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
<!-- ... -->
</select>
}}}

You can check the following code using the
[https://validator.w3.org/#validate_by_input W3C validation service]:


{{{#!text/html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Validation test</title>
</head>
<body>
<select id="id_some_field" name="some_field" required>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
<!-- ... -->
</select>
</body>
</html>
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27370>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Oct 20, 2016, 3:35:33 PM10/20/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody

Type: Bug | Status: new
Component: Forms | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
HTML,Select,wdiget,ModelChoiceField| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by alexpirine):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Old description:

New description:

I didn't think it was wrong in HTML, but the W3C validator says so, and

after reading this discussion, it seems to be right:

https://github.com/validator/validator/issues/47

Example:

results in:

--

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:1>

Django

unread,
Oct 20, 2016, 3:37:03 PM10/20/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
HTML,Select,wdiget,ModelChoiceField| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by alexpirine:

Old description:

> I didn't think it was wrong in HTML, but the W3C validator says so, and

> after reading this discussion, it seems to be right:

New description:

I didn't think it was wrong in HTML, but the W3C validator says so, and

after reading this discussion, it seems to be right:

https://github.com/validator/validator/issues/47

Example:

results in:

In order to fix this, the generated `<select>` widget should not have a
`required` attribute.

--

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:2>

Django

unread,
Oct 21, 2016, 3:20:23 AM10/21/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Claude Paroz):

* version: 1.10 => master
* type: Bug => Cleanup/optimization
* stage: Unreviewed => Accepted


Comment:

Here's the validator error message:
`The first child option element of a select element with a required
attribute, and without a multiple attribute, and without a size attribute
whose value is greater than 1, must have either an empty value attribute,
or must have no text content. Consider either adding a placeholder option
label, or adding a size attribute with a value equal to the number of
option elements.`
At first sight, this should be doable without difficulty in the widget's
`use_required_attribute` method.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:3>

Django

unread,
Oct 25, 2016, 5:32:33 AM10/25/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Andrew Nester):

Agree with Claude Paroz - all we need to do is to set
{{{use_required_attribute = False}}} in form where such field used.
Something like this:

{{{
class TestForm(forms.Form):
use_required_attribute = False

some_field = forms.ModelChoiceField(queryset=SomeModel.objects.all(),
empty_label=None)
}}}

I guess we don't need some additional changes for this, what do you think
@alexpirine?

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:4>

Django

unread,
Oct 25, 2016, 8:35:38 AM10/25/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Claude Paroz):

If Django has all needed elements to determine the value of
`use_required_attribute` in such a situation, it should do it
automatically and not require the user to add it explicitly.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:5>

Django

unread,
Oct 25, 2016, 8:47:13 AM10/25/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by alexpirine):

I agree with Claude.

Also, `use_required_attribute` applies to all fields, which is not desired
here. We only want to remove the required attribute from the Select
widget.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:6>

Django

unread,
Oct 25, 2016, 10:35:44 AM10/25/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Jon Dufresne):

alexpirine, I believe Claude is referring to
[https://github.com/django/django/blob/adc93e85990b644194c679f528225deed9fdaa85/django/forms/widgets.py#L254-L255
Widget.use_required_attribute], not `Form.use_required_attribute`. For
reference, this method will be documented
[https://github.com/django/django/pull/7419 soon].

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:7>

Django

unread,
Nov 5, 2016, 5:20:07 AM11/5/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned

Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Josef Rousek):

* owner: nobody => Josef Rousek
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:8>

Django

unread,
Nov 5, 2016, 10:58:19 AM11/5/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Josef Rousek):

* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/7497 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:9>

Django

unread,
Nov 5, 2016, 12:32:31 PM11/5/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by alexpirine):

I reviewed the code:

The overall logic and tests seem to be correct, except in case of an empty
<select>.

But I can not make a full judgment about the code, since I lack the
understanding of some parts of `widgets.py`. For instance I didn't know
anything about the `renderer` attribute (I still can not find it in
documentation).

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:10>

Django

unread,
Nov 5, 2016, 12:36:56 PM11/5/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
HTML,Select,wdiget,ModelChoiceField|
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Josef Rousek):

Replying to [comment:10 alexpirine]:


> I reviewed the code:
>
> The overall logic and tests seem to be correct, except in case of an
empty <select>.
>
> But I can not make a full judgment about the code, since I lack the
understanding of some parts of `widgets.py`. For instance I didn't know
anything about the `renderer` attribute (I still can not find it in
documentation).

Thanks for review! I'll fix those issues.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:11>

Django

unread,
Nov 11, 2016, 7:43:58 AM11/11/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin

Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):

* stage: Accepted => Ready for checkin


Comment:

Patch LGTM pending some cosmetic comments.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:12>

Django

unread,
Nov 11, 2016, 1:15:33 PM11/11/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: assigned
Component: Forms | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Josef Rousek):

I applied those cosmetic changes.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:13>

Django

unread,
Dec 28, 2016, 11:07:36 AM12/28/16
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: closed
Component: Forms | Version: master
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"aaecf038cae61f114db396f74e06759c95f21e93" aaecf038]:
{{{
#!CommitTicketReference repository=""
revision="aaecf038cae61f114db396f74e06759c95f21e93"
Fixed #27370 -- Prevented Select widget from using 'required' with a non-
empty first value.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:14>

Django

unread,
Feb 27, 2020, 3:38:50 AM2/27/20
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: closed
Component: Forms | Version: master
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Aurélien Pardon):

There is a huge performance regression as a side-effect of
[changeset:"aaecf038cae61f114db396f74e06759c95f21e93" aaecf038]. For
{{{ModelChoiceField}}} with {{{empty_label=None}}}, it doubles the queries
to the database.

With this {{{simple_app/models.py}}}:
{{{#!python
from django.db import models

class MyModel(models.Model):
my_field = models.CharField(max_length=1)
}}}

the following code:
{{{#!python
from django import forms
from simple_app.models import MyModel

class MyForm(forms.Form):
my_form_field = forms.ModelChoiceField(MyModel.objects.all(),
empty_label=None)

MyForm().as_ul()
}}}

makes two times the same request to the database:
{{{#!python
>>> from django.db import connection
>>> from django.db import reset_queries
>>> reset_queries()
>>> _ = MyForm().as_ul()
>>> connection.queries
[{'sql': 'SELECT "simple_app_mymodel"."id",
"simple_app_mymodel"."my_field" FROM "simple_app_mymodel"',
'time': '0.000'},
{'sql': 'SELECT "simple_app_mymodel"."id",
"simple_app_mymodel"."my_field" FROM "simple_app_mymodel"',
'time': '0.000'}]
}}}

Before this commit, it only makes one request (as intended IMO):
{{{#!python
>>> from django.db import connection
>>> from django.db import reset_queries
>>> reset_queries()
>>> _ = MyForm().as_ul()
>>> connection.queries
[{'sql': 'SELECT "simple_app_mymodel"."id",
"simple_app_mymodel"."my_field" FROM "simple_app_mymodel"',
'time': '0.000'}]
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:15>

Django

unread,
Feb 27, 2020, 3:39:39 AM2/27/20
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: closed
Component: Forms | Version: master
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Aurélien Pardon):

* cc: Aurélien Pardon (added)
* needs_better_patch: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:16>

Django

unread,
Feb 27, 2020, 7:54:06 AM2/27/20
to django-...@googlegroups.com
#27370: Django's Select widget adds a required="required" attribute, even if
created with empty_label=True
-------------------------------------+-------------------------------------
Reporter: alexpirine | Owner: Josef
Type: | Rousek
Cleanup/optimization | Status: closed
Component: Forms | Version: master
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
HTML,Select,wdiget,ModelChoiceField| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* needs_better_patch: 1 => 0


Comment:

Follow-up in #31295.

--
Ticket URL: <https://code.djangoproject.com/ticket/27370#comment:17>

Reply all
Reply to author
Forward
0 new messages