【问题标题】:Django radio buttons appearing as bullet point list, inside mark_safe()Django 单选按钮在 mark_safe() 内显示为项目符号列表
【发布时间】:2020-08-11 03:22:46
【问题描述】:

背景

我在表单中使用了 'mark_safe()' 来传递 HTML 指令并在我的表单标签中显示要点:

class FormFood(forms.Form):
    CHOICES = [ (1,'Yes'), (2, 'No')]
    response = forms.ChoiceField(widget=forms.RadioSelect,
              label=mark_safe("Do you like any of these foods? <ul><li>Pasta</li><li>Rice</li><li>Cheese</li></ul>"), choices=CHOICES)

这输出为:

问题

正如您在上面看到的,尽管我不希望这样,但项目符号现在也出现在“是”和“否”旁边。检查元素显示这是因为它们也是在无序列表标签内构建的(尽管我的 ul 标签在上面的标签中以 'cheese' 结尾):

<form method="POST">
    <label for="id_response_0">Do you like any of these foods?
        <ul>
            <li>Pasta</li>
            <li>Rice</li>
            <li>Cheese</li>
        </ul>
    </label>
    <ul id="id_response">
        <li>
            <label for="id_response_0">
                <input type="radio" name="response" value="1" required="" id="id_response_0"> Yes
            </label>

        </li>
        <li>
            <label for="id_response_1">
                <input type="radio" name="response" value="2" required="" id="id_response_1"> No
            </label>

        </li>
    </ul>
    <input type="hidden" name="csrfmiddlewaretoken" value="FaOTY4WlVLFMl3gNtut8BJihJKub1Is0wRJRxxLck1e2eJocJVXRiGoOLDr9jdvx">
    <input type="submit">
</form>

有没有办法可以阻止这种情况,只保留“意大利面”、“米饭”和“奶酪”上的要点,同时从“是”和“否”中删除要点/列表?

【问题讨论】:

  • This 可能会有所帮助。
  • 我明白了,用 CSS 添加一个类和目标。那应该行得通。我想知道是否可以从后端做一些更优雅的事情,但前端修复也可以。谢谢
  • 你的 ul 标签结尾不正确吗? &lt;&lt;/ul&gt;
  • 嗨 MogitC,好发现!只是解决了这个问题。不幸的是,在这里而不是在我的代码中转移时是一个错字

标签: python html django python-3.x django-forms


【解决方案1】:

RadioSelect 小部件使用&lt;ul&gt; 元素来列出选项。默认情况下,浏览器会显示 &lt;ul&gt; 元素,并带有一个项目符号,并且每个元素的左侧通常有 40 像素的内边距。

有三种方法可以解决此问题。您可以添加一些基本的 CSS。这三种方法按推荐顺序给出。到目前为止,最好的选择是使用 CSS。

1。使用 CSS

这是最好的选择。选择这个。

首先:class 属性添加到您的RadioSelect 小部件。

# forms.py

class FormFood(forms.Form):
    CHOICES = [ (1,'Yes'), (2, 'No')]
    response = forms.ChoiceField(
        widget=forms.RadioSelect(attrs={'class': "custom-radio-list"}),
        label=mark_safe("Do you like any of these foods? <ul><li>Pasta</li><li>Rice</li><li>Cheese</li></ul>"), choices=CHOICES)

第二:添加一些CSS。

.custom-radio-list {
    list-style-type: none;
    padding: 0;
    margin: 0;
}

为了让这个答案更加完整和全面,提供了以下方法。有时您需要修改 HTML 或创建自定义小部件。但是,在您的情况下,CSS 是最佳选择。演示文稿应主要使用 CSS 处理。

2。创建自定义小部件

对于简单的小部件,创建自定义小部件非常简单。

首先:创建一个继承自 RadioSelect 类的自定义小部件,然后将其用作您的字段的小部件。

# forms.py

from django import forms


class MyRadioWidget(RadioSelect):
    template_name = 'myradiowidget.html'


class FormFood(forms.Form):
    CHOICES = [ (1,'Yes'), (2, 'No')]
    response = forms.ChoiceField(
        widget=MyRadioWidget,
        label=mark_safe("Do you like any of these foods? <ul><li>Pasta</li><li>Rice</li><li>Cheese</li></ul>"), choices=CHOICES)

第二:添加一个使用&lt;div&gt;元素而不是&lt;ul&gt;&lt;li&gt;元素的HTML模板。

<!-- /templates/myradiowidget.html -->

{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
  <div>{{ group }}<div{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %}
    <div>{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
  </div></div>{% endif %}{% endfor %}
</div>{% endwith %}

3。覆盖默认的表单 HTML

您可以覆盖表单小部件 HTML 模板。

注意:这将覆盖整个项目的模板,包括 Django 管理员!

首先:将表单模板渲染器更改为使用 Django 模板后端。

# settings.py

FORM_RENDERER = "django.forms.renderers.TemplatesSetting"

第二:将新的radio.html 文件添加到template 目录以覆盖默认小部件。

<!-- /templates/django/forms/widgets/radio.html -->

{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
  <div>{{ group }}<div{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %}
    <div>{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
  </div></div>{% endif %}{% endfor %}
</div>{% endwith %}

【讨论】:

  • 选项 4:循环遍历模板中的单选字段,如 docs 中所述
  • 无需添加自定义类,您只需在 CSS 中选择 &lt;ul&gt; 元素 id:#id_response
  • @djvg 选项 4 是最简单的解决方案。完美运行。
猜你喜欢
  • 2013-07-14
  • 2012-09-18
  • 1970-01-01
  • 2011-07-07
  • 2015-07-09
  • 2020-07-26
  • 2018-07-14
  • 1970-01-01
  • 2012-04-03
相关资源
最近更新 更多