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