Opened 4 years ago
Closed 4 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 , 4 years ago
Description: | modified (diff) |
---|
comment:2 by , 4 years ago
comment:3 by , 4 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 , 4 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 , 4 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