Align radio buttons horizontally in django forms

前端 未结 7 1783
借酒劲吻你
借酒劲吻你 2021-02-08 01:50

HI

I want to align the radio buttons horizontally. By default django forms displays in vertical format.

feature_type  = forms.TypedChoiceField(choices =         


        
相关标签:
7条回答
  • 2021-02-08 02:31

    On my Django 2.2.6 above solutions did not worked well, so I post my solution after many tries and following the breadcrumbs until the django forms widget templates used.

    I had to override 2 templates, and heritage my own widget class and then point it.

    The modified default django templates have been:

    • django/forms/templates/django/forms/widgets/input_option.html
    • django/forms/templates/django/forms/widgets/multiple_input.html

    Now they are:

    PROJECT_NAME/PROJECT_APP/templates/admin/horizontal_option.html

    {% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %} class="radio-inline">{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
    

    PROJECT_NAME/PROJECT_APP/templates/admin/horizontal_radios.html

    {% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
      <li>{{ group }}
        <ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %}
        {% include option.template_name with widget=option %}{% endfor %}{% if group %}
      </ul></li>{% endif %}{% endfor %}
    </ul>{% endwith %}
    
    • The first one includes a hardcoded class: class="radio-inline" at labels, which in default Django had nothing
    • The second one the rendering of the set of radios, I removed the extra HTML li tags they were rendered inside the internal ul tag.

    Then you need to create your own widget class:

    from django.forms import RadioSelect
    
    
    class HorizontalRadioSelect(RadioSelect):
        template_name = 'admin/horizontal_radios.html'
        option_template_name = 'admin/horizontal_inputs.html'
    

    And finally, in my case, I pointed to it overriding formfield_overrides class attribute in my admin. But you can do this in your models too I think:

        formfield_overrides = {
            models.BooleanField: {'widget': HorizontalRadioSelect(choices=[(True, "Yes"), (False, "No"), (None, "Unknown")],)},
        }
    
    0 讨论(0)
  • 2021-02-08 02:36

    According to the Django docs 'attrs' is a dictionary containing HTML attributes to be set on the rendered widget.

    With that in mind a simple form based solution would be something like the following:

    feature_type  = forms.TypedChoiceField(
        choices = formfields.FeatureType,
        widget = forms.RadioSelect(attrs={
            'style': 'display: inline-block'
        })
    )
    
    0 讨论(0)
  • There is actually no need to override the widget, template or anything else in admin. At least since 2008 (see forms.css), the easiest way is to pass a class attribute inline: attrs={'class': 'inline'}

    In a custom form, it may look like:

    field = forms.ChoiceField(choices=(('1', 'one'), ('2', 'two')),
                              widget=forms.RadioSelect(attrs={'class': 'inline'}))
    

    … and it works the very same for checkboxes:

    field = forms.MultipleChoiceField(choices=(('1', 'one'), ('2', 'two')),
                                      widget=forms.CheckboxSelectMultiple(attrs={'class': 'inline'}))
    

    And it should be the very same for formfield overrides, either via ModelAdmin formfield_overrides or formfield_for_* functions.

    0 讨论(0)
  • 2021-02-08 02:45

    Thats the behavior of the RadioField. If you want it rendered horizontally, create a horizontal renderer, like something as follows:

    from django.utils.safestring import mark_safe
    
    class HorizontalRadioRenderer(forms.RadioSelect.renderer):
      def render(self):
        return mark_safe(u'\n'.join([u'%s\n' % w for w in self]))
    
    
    class ApprovalForm(forms.Form):
        approval = forms.ChoiceField(choices=APPROVAL_CHOICES,
                     initial=0,
                     widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
                                     )
    
    0 讨论(0)
  • 2021-02-08 02:46

    Another way out is to changing the style of ul->li list to display:inline-block. You can do something like that

     <style>
     ul#youelementId li{
      display: inline-block;
      }
    </style>
    

    hope this would help next reader.

    0 讨论(0)
  • 2021-02-08 02:50

    I've come up with an alternative solution. If you are using bootstrap to render your forms, you can add the .form-check-inline class to the input and the field will display horizontally. Listed below is code that shows what I'm describing. I hope this helps someone from reinventing the wheel. Thanks for reading. Take care and have a good day.

                    feature_type = forms.MultipleChoiceField(
                    required=False,
                    ...
                    widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-inline'})
                    )
    

    0 讨论(0)
提交回复
热议问题