在Django中只渲染MultiWidget的一部分

时间:2014-07-21 13:58:45

标签: django django-forms django-widget

我有一个Django表单字段,其中包含一个由两个TextInputs组成的MultiWidget。

在模板中渲染表单时,有一个方便的符号

{{ formname.fieldname }}

用于渲染单个字段。当我将它用于具有MultiWidget的字段时,它将显示两个HTML输入元素。是否会略微修改仅显示第一个HTML输入元素的符号? ({{ formname.fieldname.0 }}不起作用。)

2 个答案:

答案 0 :(得分:5)

我找到了解决这个问题的方法,需要两段代码。

<强>第一

将MultiWidget转换为字符串的render方法相对较长。我们需要在最后一行中通过微小的修改来复制和粘贴它,以使其反转为数组。

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]

<强>第二

在模板中编写{{ formname.fieldname }}将自动调用字段的unicode方法并将结果视为字符串。正如我们想要一个数组,我们需要绕过unicode方法并直接访问它将返回的内容。这是方法as_widget。因此,要调用OurMultiWidget的第一部分,我们将需要在模板中使用此代码:

{{ formname.fieldname.as_widget.0 }}

答案 1 :(得分:0)

Philipp Zedler 的回答令人惊奇,但不适用于 Django 3.1,因为渲染的工作方式发生了变化。不幸的是,Django 3.1 的 MultiWidget 似乎有点损坏,因此遍历子小部件仍然不能正常工作,但幸运的是修复要简单得多。

MultiWidget 似乎缺少以下方法覆盖:

    def subwidgets(self, name, value, attrs=None):
        context = self.get_context(name, value, attrs)
        return context['widget']['subwidgets']

如果您将此方法添加到您自己的 MultiWidget 子类中,您将能够按如下方式遍历子小部件:

<h2>{{ form.myfield.label }}</h2>
<ul>
  {% for w in form.myfield.subwidgets %}
  <li>{{ w }}</li>
  {% endfor %}
</ul>