Przeglądaj źródła

Fixed #34532 -- Made formset_factory() respect Form's default_renderer.

Co-authored-by: David Smith <smithdc@gmail.com>
Christopher Cave-Ayland 1 rok temu
rodzic
commit
95e4d6b813

+ 5 - 3
django/forms/formsets.py

@@ -99,6 +99,8 @@ class BaseFormSet(RenderableFormMixin):
         self.error_class = error_class
         self._errors = None
         self._non_form_errors = None
+        self.form_renderer = self.renderer
+        self.renderer = self.renderer or get_default_renderer()
 
         messages = {}
         for cls in reversed(type(self).__mro__):
@@ -224,7 +226,7 @@ class BaseFormSet(RenderableFormMixin):
             # incorrect validation for extra, optional, and deleted
             # forms in the formset.
             "use_required_attribute": False,
-            "renderer": self.renderer,
+            "renderer": self.form_renderer,
         }
         if self.is_bound:
             defaults["data"] = self.data
@@ -261,7 +263,7 @@ class BaseFormSet(RenderableFormMixin):
             "prefix": self.add_prefix("__prefix__"),
             "empty_permitted": True,
             "use_required_attribute": False,
-            "renderer": self.renderer,
+            "renderer": self.form_renderer,
         }
         form = self.form(**form_kwargs)
         self.add_fields(form, None)
@@ -566,7 +568,7 @@ def formset_factory(
         "absolute_max": absolute_max,
         "validate_min": validate_min,
         "validate_max": validate_max,
-        "renderer": renderer or get_default_renderer(),
+        "renderer": renderer,
     }
     return type(form.__name__ + "FormSet", (formset,), attrs)
 

+ 59 - 1
tests/forms_tests/tests/test_formsets.py

@@ -23,7 +23,11 @@ from django.forms.formsets import (
     all_valid,
     formset_factory,
 )
-from django.forms.renderers import TemplatesSetting
+from django.forms.renderers import (
+    DjangoTemplates,
+    TemplatesSetting,
+    get_default_renderer,
+)
 from django.forms.utils import ErrorList
 from django.forms.widgets import HiddenInput
 from django.test import SimpleTestCase
@@ -1553,6 +1557,60 @@ class FormsFormsetTestCase(SimpleTestCase):
         self.assertEqual(formset.non_form_errors().renderer, renderer)
         self.assertEqual(formset.empty_form.renderer, renderer)
 
+    def test_form_default_renderer(self):
+        """
+        In the absence of a renderer passed to the formset_factory(),
+        Form.default_renderer is respected.
+        """
+
+        class CustomRenderer(DjangoTemplates):
+            pass
+
+        class ChoiceWithDefaultRenderer(Choice):
+            default_renderer = CustomRenderer()
+
+        data = {
+            "choices-TOTAL_FORMS": "1",
+            "choices-INITIAL_FORMS": "0",
+            "choices-MIN_NUM_FORMS": "0",
+        }
+
+        ChoiceFormSet = formset_factory(ChoiceWithDefaultRenderer)
+        formset = ChoiceFormSet(data, prefix="choices")
+        self.assertEqual(
+            formset.forms[0].renderer, ChoiceWithDefaultRenderer.default_renderer
+        )
+        self.assertEqual(
+            formset.empty_form.renderer, ChoiceWithDefaultRenderer.default_renderer
+        )
+        default_renderer = get_default_renderer()
+        self.assertIsInstance(formset.renderer, type(default_renderer))
+
+    def test_form_default_renderer_class(self):
+        """
+        In the absence of a renderer passed to the formset_factory(),
+        Form.default_renderer is respected.
+        """
+
+        class CustomRenderer(DjangoTemplates):
+            pass
+
+        class ChoiceWithDefaultRenderer(Choice):
+            default_renderer = CustomRenderer
+
+        data = {
+            "choices-TOTAL_FORMS": "1",
+            "choices-INITIAL_FORMS": "0",
+            "choices-MIN_NUM_FORMS": "0",
+        }
+
+        ChoiceFormSet = formset_factory(ChoiceWithDefaultRenderer)
+        formset = ChoiceFormSet(data, prefix="choices")
+        self.assertIsInstance(formset.forms[0].renderer, CustomRenderer)
+        self.assertIsInstance(formset.empty_form.renderer, CustomRenderer)
+        default_renderer = get_default_renderer()
+        self.assertIsInstance(formset.renderer, type(default_renderer))
+
     def test_repr(self):
         valid_formset = self.make_choiceformset([("test", 1)])
         valid_formset.full_clean()

+ 43 - 0
tests/model_formsets/tests.py

@@ -9,10 +9,12 @@ from django.db import models
 from django.forms.formsets import formset_factory
 from django.forms.models import (
     BaseModelFormSet,
+    ModelForm,
     _get_foreign_key,
     inlineformset_factory,
     modelformset_factory,
 )
+from django.forms.renderers import DjangoTemplates
 from django.http import QueryDict
 from django.test import TestCase, skipUnlessDBFeature
 
@@ -2365,3 +2367,44 @@ class TestModelFormsetOverridesTroughFormMeta(TestCase):
         BookFormSet = modelformset_factory(Author, fields="__all__", renderer=renderer)
         formset = BookFormSet()
         self.assertEqual(formset.renderer, renderer)
+
+    def test_modelformset_factory_default_renderer(self):
+        class CustomRenderer(DjangoTemplates):
+            pass
+
+        class ModelFormWithDefaultRenderer(ModelForm):
+            default_renderer = CustomRenderer()
+
+        BookFormSet = modelformset_factory(
+            Author, form=ModelFormWithDefaultRenderer, fields="__all__"
+        )
+        formset = BookFormSet()
+        self.assertEqual(
+            formset.forms[0].renderer, ModelFormWithDefaultRenderer.default_renderer
+        )
+        self.assertEqual(
+            formset.empty_form.renderer, ModelFormWithDefaultRenderer.default_renderer
+        )
+        self.assertIsInstance(formset.renderer, DjangoTemplates)
+
+    def test_inlineformset_factory_default_renderer(self):
+        class CustomRenderer(DjangoTemplates):
+            pass
+
+        class ModelFormWithDefaultRenderer(ModelForm):
+            default_renderer = CustomRenderer()
+
+        BookFormSet = inlineformset_factory(
+            Author,
+            Book,
+            form=ModelFormWithDefaultRenderer,
+            fields="__all__",
+        )
+        formset = BookFormSet()
+        self.assertEqual(
+            formset.forms[0].renderer, ModelFormWithDefaultRenderer.default_renderer
+        )
+        self.assertEqual(
+            formset.empty_form.renderer, ModelFormWithDefaultRenderer.default_renderer
+        )
+        self.assertIsInstance(formset.renderer, DjangoTemplates)