From cc5901fa8edc25ce6d67d110c18ddf9f16965e32 Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Mon, 16 Oct 2023 19:11:18 +0100 Subject: [5.0.x] Fixed #34899 -- Added blank choice to forms' callable choices lazily. Backport of 171f91d9ef5177850c2f12b26dd732785f6ac034 from main --- tests/model_forms/tests.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'tests/model_forms') diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index d1716ce201..43bb770f7e 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -23,6 +23,7 @@ from django.forms.models import ( from django.template import Context, Template from django.test import SimpleTestCase, TestCase, ignore_warnings, skipUnlessDBFeature from django.test.utils import isolate_apps +from django.utils.choices import BlankChoiceIterator from django.utils.deprecation import RemovedInDjango60Warning from .models import ( @@ -2012,6 +2013,38 @@ class ModelFormBasicTests(TestCase): ), ) + @isolate_apps("model_forms") + def test_callable_choices_are_lazy(self): + call_count = 0 + + def get_animal_choices(): + nonlocal call_count + call_count += 1 + return [("LION", "Lion"), ("ZEBRA", "Zebra")] + + class ZooKeeper(models.Model): + animal = models.CharField( + blank=True, + choices=get_animal_choices, + max_length=5, + ) + + class ZooKeeperForm(forms.ModelForm): + class Meta: + model = ZooKeeper + fields = ["animal"] + + self.assertEqual(call_count, 0) + form = ZooKeeperForm() + self.assertEqual(call_count, 0) + self.assertIsInstance(form.fields["animal"].choices, BlankChoiceIterator) + self.assertEqual(call_count, 0) + self.assertEqual( + form.fields["animal"].choices, + models.BLANK_CHOICE_DASH + [("LION", "Lion"), ("ZEBRA", "Zebra")], + ) + self.assertEqual(call_count, 1) + def test_recleaning_model_form_instance(self): """ Re-cleaning an instance that was added via a ModelForm shouldn't raise -- cgit v1.3