在 Django 中仅渲染 MultiWidget 的一部分

Posted

技术标签:

【中文标题】在 Django 中仅渲染 MultiWidget 的一部分【英文标题】:Render only one part of a MultiWidget in Django 【发布时间】:2014-09-12 01:36:21 【问题描述】:

我有一个带有 MultiWidget 的 Django 表单字段,它由两个 TextInputs 组成。

在模板中呈现表单时,有方便的表示法

 formname.fieldname 

用于渲染单个字段。当我将它用于带有 MultiWidget 的字段时,它将显示两个 html 输入元素。是否对仅显示第一个 HTML 输入元素的表示法进行了轻微修改? ( formname.fieldname.0 不起作用。)

【问题讨论】:

【参考方案1】:

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>

【讨论】:

【参考方案2】:

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

第一

将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 

【讨论】:

天哪,我已经找了好几个小时了。谢谢!

以上是关于在 Django 中仅渲染 MultiWidget 的一部分的主要内容,如果未能解决你的问题,请参考以下文章

Django MultiWidget 电话号码字段

Django子类化multiwidget - 使用自定义multiwidget重建帖子日期

如何使用 Django 的 MultiWidget?

在自动完成中仅渲染某些项目

在 DOM 中仅渲染子元素而不是整个 JSX 元素

使用python在OpenGL中仅渲染立方体内的一部分球体?