django form radio input layout

前端 未结 4 880
醉话见心
醉话见心 2021-01-02 17:05

What is the \"djangoy\" way to approach this problem:

In my form class, I have a forms.ChoiceField whose widget is a forms.RadioSelect widget, one of whose choices n

4条回答
  •  醉话见心
    2021-01-02 17:39

    Anton's answer worked, and was a decent answer for a while there - but unfortunately it became unmaintainable. So, taking a cue from a diff attached to django ticket #9230, I just monkey patched django.forms.forms.BoundField

    from django import forms
    
    def MonkeyPatchDjangoFormsBoundField():
        def prepare_widget_render(self, widget=None, attrs=None, only_initial=False):
            """
            Prepare the data needed for the widget rendering.
            """
            if not widget:
                widget = self.field.widget
    
            attrs = attrs or {}
            auto_id = self.auto_id
            if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
                if not only_initial:
                    attrs['id'] = auto_id
                else:
                    attrs['id'] = self.html_initial_id
    
            if not only_initial:
                name = self.html_name
            else:
                name = self.html_initial_name
    
            return widget, name, attrs
    
        def as_widget(self, widget=None, attrs=None, only_initial=False):
            """
            Renders the field by rendering the passed widget, adding any HTML
            attributes passed as attrs.  If no widget is specified, then the
            field's default widget will be used.
            """
            widget, name, attrs = self.prepare_widget_render(widget, attrs, only_initial)
            return widget.render(name, self.value(), attrs=attrs)
    
        def __iter__(self):
            """
            Check if current widget has a renderer and iterate renderer.
            """
            widget, name, attrs = self.prepare_widget_render()
            if not hasattr(widget, 'get_renderer'):
                raise Exception, "Can not iterate over widget '%s'" % widget.__class__.__name__
            renderer = widget.get_renderer(name, self.value(), attrs=attrs)
            for entry in renderer:
                yield entry
    
        def __getitem__(self,idx):
            """
            Tries to use current widget's renderer, and then check attribute.
            """
            widget, name, attrs = self.prepare_widget_render()
            try:
                renderer = widget.get_renderer(name, self.value(), attrs=attrs)
                return renderer[idx]
            except Exception:
                return getattr(self,idx)
    
        forms.forms.BoundField.prepare_widget_render = prepare_widget_render
        forms.forms.BoundField.as_widget = as_widget
        forms.forms.BoundField.__iter__ = __iter__
        forms.forms.BoundField.__getitem__ = __getitem__
    

    This allowed me to be able to access the radio inputs directly, by using {{ form.field.0.tag }}, or through iteration - {% for radio in form.field %} {{ radio.tag }} {% endfor %}. Much easier to take care of!

提交回复
热议问题