热门标签:
Q:

在django表单中水平对齐单选按钮

嗨。

我想水平对齐单选按钮。 默认情况下,django表单以垂直格式显示。

feature_type  = forms.TypedChoiceField(choices = formfields.FeatureType, widget = forms.RadioSelect)

是否有任何特殊的参数,我们可以传递单选按钮对齐?

提前致谢

原网址
A:

这就是RadioField的行为。 如果你想水平渲染,创建一个水平渲染器,如下所示:

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),
                                 )

所有回答

共 9 条

author avatar

另一种方法是将ul->li列表的样式更改为display:inline-block。 你可以做这样的事情

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

希望这将有助于下一个读者。

author avatar

我想出了一个替代解决方案。 如果您使用bootstrap来呈现表单,则可以添加。form-check-inline类到输入,字段将水平显示。 下面列出的代码显示了我所描述的内容。 我希望这可以帮助某人重新发明轮子。 谢谢你的阅读。 保重,祝你有美好的一天。

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

<img alt="此图像显示水平显示的一组单选按钮。"src="https://i.stack.imgur.com/dIrRi.png缧/>

author avatar

在我的Django2.2.6上面的解决方案效果不佳,所以我在多次尝试并遵循面包屑之后发布我的解决方案,直到使用django表单小部件模板。

我不得不复盖2个模板,并创建我自己的小部件类,然后指向它。

修改后的默认django模板已:

  • django/forms/templates/django/forms/widgets/input_option。html格式
  • django/forms/templates/django/forms/widgets/multiple_input。html格式

现在他们是:

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 %}
  • 第一个包含一个硬编码类:class="radio-inline"at标签,默认情况下Django没有任何东西
  • 第二个是一组无线电的渲染,我删除了它们在内部ul标签中渲染的额外HTML li标签。

然后你需要创建自己的小部件类:

from django.forms import RadioSelect


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

最后,在我的情况下,我指出它在我的admin中复盖formfield_overrides类属性。 但你也可以在你的模型中做到这一点我认为:

    formfield_overrides = {
        models.BooleanField: {'widget': HorizontalRadioSelect(choices=[(True, "Yes"), (False, "No"), (None, "Unknown")],)},
    }
author avatar

修改形式。RadioSelect:

class HorizontalRadioSelect(forms.RadioSelect):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        css_style = 'style="display: inline-block; margin-right: 10px;"'

        self.renderer.inner_html = '<li ' + css_style + '>{choice_value}{sub_widgets}</li>'

使用Django1.10的standart管理员处理Python3.4 在这里输入图像描述http://djangosuit.com/)(它使用Bootstrap的2种样式)

<img alt="在这里输入图像描述"src="https://i.stack.imgur.com/J1RNO.png缧/>

尚未针对Django-grappelli进行测试。

author avatar

根据Django docs'attrs'是一个包含要在呈现的小部件上设置的HTML属性的字典。

考虑到这一点,一个简单的基于表单的解决方案将如下所示:

feature_type  = forms.TypedChoiceField(
    choices = formfields.FeatureType,
    widget = forms.RadioSelect(attrs={
        'style': 'display: inline-block'
    })
)
author avatar

实际上不需要复盖admin中的小部件,模板或其他任何内容。 至少自2008年以来(见表格。css),最简单的方法就是传递一个类属性inline:attrs={'class': 'inline'}

在自定义表单中,它可能看起来像:

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

...它的工作原理非常相同的复选框:

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

对于formfield复盖,它应该是相同的,无论是通过ModelAdminformfield_overrides还是formfield_for_*函数。

author avatar

当renerer为我提出这个错误时:

AttributeError:类型对象'RadioSelect'没有属性'renderer'

我想出了这个代码:

<form method="post">
    {% csrf_token %}
    {% for question in form %}
        <p>{{ question.label }}: </p>
        {% for choice in question %}
            {{ choice }}
        {% endfor %}
    {% endfor %}
    <br><br>
    <button type="submit">
            submit
    </button>

</form>
author avatar

您可以使用此方法。 在我看来,这是最简单的

class YourAdminForm(forms.ModelForm):

    class Meta:
        model = models.YourModel
        widgets = {
            "your_field": forms.RadioSelect(attrs={"class": "inline"}),
        }

或者只是定义你的领域是这样的

    your_field = forms.ChoiceField(
        choices=(...),
        widget=forms.RadioSelect(attrs={"class": "inline"}),
    )
author avatar

为那些使用django-crispy-forms和使用|as_crispy_field渲染字段的人添加这个。 上面的解决方案都不适合我,但这确实如此:

假设你的表单中有这样的东西:

class MyModelForm(forms.ModelForm):
    class Meta: 
        model = MyModel
        fields = ['your_field_name']

    your_field_name = forms.ChoiceField(widget=forms.RadioSelect(), choices=YOUR_CHOICE_LIST)

...而这在你的模板:

<div class="row g-3">
    <div class="col-md-12">
        {{ form.your_field_name|as_crispy_field }}
    </div>
</div>

下面的CSS做的伎俩:

<style>
    #div_id_your_field_name div {
        display:inline-flex;
        width: 100%;
    } /* Renders the radio buttons inline and spreads across your div */
    
    #div_id_your_field_name .form-check-label {
        margin-left: 10px;

    } /* puts a bit of space between the radio and label */
    
    #div_id_your_field_name .form-label {
        display: none;

    } /* Optional, if you want to suppress the default label for some reason */
</style>

相似问题