Render only one part of a MultiWidget in Django

前端 未结 1 1203
灰色年华
灰色年华 2020-12-19 23:45

I have a Django Form Field with a MultiWidget that consists of two TextInputs.

When rendering the form in a template there is the handy notation

{{ f         


        
相关标签:
1条回答
  • 2020-12-20 00:15

    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 }}
    
    0 讨论(0)
提交回复
热议问题