5👍
I found a solution to this problem that needs two pieces of code.
First
The render
method that turns the MultiWidget into a string is relatively long. We need to copy&paste it with a tiny modification in the last line to make it returing an array instead.
class OurMultiWidget(forms.MultiWidget):
...
def render(self, name, value, attrs=None):
"""Copy and past from original render method"""
if self.is_localized:
for widget in self.widgets:
widget.is_localized = self.is_localized
# value is a list of values, each corresponding to a widget
# in self.widgets.
if not isinstance(value, list):
value = self.decompress(value)
output = []
final_attrs = self.build_attrs(attrs)
id_ = final_attrs.get('id', None)
for i, widget in enumerate(self.widgets):
try:
widget_value = value[i]
except IndexError:
widget_value = None
if id_:
final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
# Original:
# return mark_safe(self.format_output(output))
# Only this line was written by myself:
return [mark_safe(self.format_output(x)) for x in output]
Second
Writing {{ formname.fieldname }}
in the template will automatically call the field’s unicode method and treat the result as a string. As we want an array instead, we need to circumvent the unicode method and access directly what it will return. And this is the method as_widget
. Thus, to call the first part of OurMultiWidget
, we will need this code in the template:
{{ formname.fieldname.as_widget.0 }}
2👍
Philipp Zedler’s answer is amazing, but doesn’t work on Django 3.1 because the way rendering works has changed. Unfortunately Django 3.1’s MultiWidget
seems a little broken so iterating through subwidgets still doesn’t Just Work, but luckily the fix is much simpler.
MultiWidget
seems to be missing the following method override:
def subwidgets(self, name, value, attrs=None):
context = self.get_context(name, value, attrs)
return context['widget']['subwidgets']
If you add this method to your own subclass of MultiWidget
, you will be able to iterate through the subwidgets as follows:
<h2>{{ form.myfield.label }}</h2>
<ul>
{% for w in form.myfield.subwidgets %}
<li>{{ w }}</li>
{% endfor %}
</ul>
- [Django]-Django filter queryset by attribute subclass
- [Django]-Django auto_add_now not working
- [Django]-How can I pass values/parameters from HTML to Django Views?