[Django] #31961: forms.ChoiceField calls choices callback multiple times.

20 views
Skip to first unread message

Django

unread,
Aug 28, 2020, 1:55:45 PM8/28/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
--------------------------------------+------------------------
Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 2.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+------------------------
I'm running:

Python 3.7
Django 2.2
Debian 4.9

If I configure a forms ChoiceField with a callback function for choices,
it gets called twice each time I render the form:


{{{
from unittest import TestCase
from django import forms

def callback():
print("callback")
return [('foo', 'bar')]

class MyForm(forms.Form):
f = forms.ChoiceField(choices=callback)


class FormTest(TestCase):
MyForm().as_p()
}}}

prints:

{{{
./manage.py test spi.test_f
callback
callback
System check identified no issues (0 silenced).

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK
}}}

This is the same sort of problem described in #26665 and/or #11390. It's
an obvious performance issue, but more than that, if can beak behavior if
the callback is non-idempotent.

I discovered this because I had patched my callback using unttest.mock to
return a sequence of return values and got hard-to-diagnose test failures.
Specifically, my test failed because it raised StopIteration when it ran
out of values to return.

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

Django

unread,
Aug 28, 2020, 2:03:30 PM8/28/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
---------------------------+--------------------------------------

Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 2.2
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------
Description changed by Roy Smith:

Old description:

New description:

I'm running:

Python 3.7
Django 2.2
Debian 4.9

If I configure a forms ChoiceField with a callback function for choices,
it gets called twice each time I render the form:


{{{
from unittest import TestCase
from django import forms

def callback():
print("callback")
return [('foo', 'bar')]

class MyForm(forms.Form):
f = forms.ChoiceField(choices=callback)


class FormTest(TestCase):
MyForm().as_p()
}}}

prints:

{{{
./manage.py test spi.test_f
callback
callback
System check identified no issues (0 silenced).

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK
}}}

This is the same sort of problem described in #26665 and/or #11390. It's

an obvious performance issue, but more than that, it can beak behavior if
the callback is non-idempotent.

I discovered this because I had patched my callback using unttest.mock to
return a sequence of return values and got hard-to-diagnose test failures.
Specifically, my test failed because it raised StopIteration when it ran
out of values to return.

--

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

Django

unread,
Aug 28, 2020, 2:03:40 PM8/28/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
---------------------------+--------------------------------------

Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 2.2
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------

Comment (by Roy Smith):

fixed typo

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

Django

unread,
Aug 29, 2020, 8:49:42 AM8/29/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
---------------------------+--------------------------------------

Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 2.2
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------

Comment (by Carlton Gibson):

Hi Roy.

Thanks for the report. Short of a concrete suggestion here, I’m struggling
to see how this isn’t just a duplicate of #11390.

[https://code.djangoproject.com/ticket/11390#comment:16 The conclusion
there seems unchanged]:

> ...I'm not sure how or if it's possible to combine the two remaining
calls...
> One's the in memory model being instantiated and the other's the
ModelForm field/widget populating it's values. They seem separate and I'm
not sure where any memoisation of this value would go or if it would be a
great idea.

Russel’s initial reply seems the appropriate workaround.

What would be your thought there?

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

Django

unread,
Aug 29, 2020, 9:08:22 AM8/29/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
---------------------------+--------------------------------------

Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 2.2
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------

Comment (by Roy Smith):

I'm not familiar with the django code internals, so I can't make any
concrete suggestions about how to fix it. At the very least, however, it
should be documented.

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

Django

unread,
Sep 1, 2020, 6:43:58 AM9/1/20
to django-...@googlegroups.com
#31961: forms.ChoiceField calls choices callback multiple times.
---------------------------+--------------------------------------

Reporter: Roy Smith | Owner: nobody
Type: Bug | Status: closed
Component: Forms | Version: 2.2
Severity: Normal | Resolution: duplicate

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------
Changes (by Carlton Gibson):

* status: new => closed
* resolution: => duplicate


Comment:

Let's close as a duplicate of #11390.

The `ChoiceField` docs already mention the evaluation during the form
initialization. I've [https://github.com/django/django/pull/13376 opened a
PR with a possible clarification].

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

Reply all
Reply to author
Forward
0 new messages