diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..21e0ca1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + "./tests", + "-p", + "*test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} \ No newline at end of file diff --git a/README.rst b/README.rst index ef848a1..ac3bd22 100644 --- a/README.rst +++ b/README.rst @@ -268,6 +268,22 @@ Output: +Fields with multiple widgets +============================ + +Some fields may render as a `MultiWidget`, composed of multiple subwidgets +(for example, a `ChoiceField` using `RadioSelect`). You can use the same tags +and filters, but your template code will need to include a for loop for fields +like this: + +.. code-block:: html+django + + {% load widget_tweaks %} + + {% for widget in form.choice %} + {{ widget|add_class:"css_class_1 css_class_2" }} + {% endfor %} + Mixing render_field and filters =============================== @@ -419,8 +435,3 @@ Make sure you have `tox `_ installed, then type tox from the source checkout. - -NOT SUPPORTED -============= - -MultiWidgets: SplitDateTimeWidget, SplitHiddenDateTimeWidget diff --git a/tests/forms.py b/tests/forms.py index 7b6a842..5cf3eb6 100644 --- a/tests/forms.py +++ b/tests/forms.py @@ -15,6 +15,7 @@ class MyForm(Form): with_attrs = CharField(widget=TextInput(attrs={"foo": "baz", "egg": "spam"})) with_cls = CharField(widget=TextInput(attrs={"class": "class0"})) date = forms.DateField(widget=SelectDateWidget(attrs={"egg": "spam"})) + choice = forms.ChoiceField(choices=[(1, "one"), (2, "two")]) def render_form(text, form=None, **context_args): diff --git a/tests/tests.py b/tests/tests.py index 80a2921..5cc9629 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -389,3 +389,14 @@ def test_field_arroba_dot(self): def test_field_double_colon_missing(self): res = render_form('{{ form.simple|attr:"::class:{active:True}" }}') assertIn(':class="{active:True}"', res) + + +class ChoiceFieldTest(TestCase): + def test_choice(self): + res = render_field("choice", "attr", "foo:bar") + assertIn("select", res) + assertIn('name="choice"', res) + assertIn('id="id_choice"', res) + assertIn('foo="bar"', res) + assertIn('', res) + assertIn('', res) diff --git a/widget_tweaks/templatetags/widget_tweaks.py b/widget_tweaks/templatetags/widget_tweaks.py index 116b3c3..87b8ce2 100644 --- a/widget_tweaks/templatetags/widget_tweaks.py +++ b/widget_tweaks/templatetags/widget_tweaks.py @@ -24,6 +24,20 @@ def _process_field_attributes(field, attr, process): attribute = params[0].replace("::", ":") value = params[1] if len(params) == 2 else True field = copy(field) + + if not hasattr(field, "as_widget"): + old_tag = field.tag + + def tag(self): # pylint: disable=unused-argument + attrs = self.data["attrs"] + process(self.parent_widget, attrs, attribute, value) + html = old_tag() + self.tag = old_tag + return html + + field.tag = types.MethodType(tag, field) + return field + # decorate field.as_widget method with updated attributes old_as_widget = field.as_widget