Opened 5 years ago
Closed 5 years ago
#31961 closed Bug (duplicate)
forms.ChoiceField calls choices callback multiple times.
| Reported by: | Roy Smith | Owned by: | nobody |
|---|---|---|---|
| Component: | Forms | Version: | 2.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
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.
Change History (5)
comment:1 by , 5 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 5 years ago
comment:3 by , 5 years ago
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.
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?
comment:4 by , 5 years ago
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.
comment:5 by , 5 years ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
Let's close as a duplicate of #11390.
The ChoiceField docs already mention the evaluation during the form initialization. I've opened a PR with a possible clarification.
fixed typo