Django 单选按钮显示为项目符号列表,在 mark_safe() 内

Tom*_*Mac 2 html python django django-forms python-3.x

背景

我在表单中使用了 '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)
Run Code Online (Sandbox Code Playgroud)

这输出为:

在此处输入图片说明

问题

正如您在上面看到的,尽管我不想要这样,但现在“是”和“否”旁边也出现了要点。检查元素发现这是因为它们也是在无序列表标签中构造的(尽管我的 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>
Run Code Online (Sandbox Code Playgroud)

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

D. *_*ell 7

RadioSelect插件使用<ul>元素列表中的选项。默认情况下,浏览器显示<ul>带有项目符号的元素,通常在每个元素的左侧填充 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)

Run Code Online (Sandbox Code Playgroud)

第二:添加一些CSS。

.custom-radio-list {
    list-style-type: none;
    padding: 0;
    margin: 0;
}
Run Code Online (Sandbox Code Playgroud)

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

2.创建自定义Widget

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

首先:创建一个从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)
Run Code Online (Sandbox Code Playgroud)

第二:添加一个使用<div>元素 not<ul><li>元素的 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 %}
Run Code Online (Sandbox Code Playgroud)

3. 覆盖默认的表单 HTML

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

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

第一:更改表单模板渲染器以使用 Django 模板后端。

# settings.py

FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
Run Code Online (Sandbox Code Playgroud)

第二:将您的新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 %}
Run Code Online (Sandbox Code Playgroud)

  • 选项 4:循环模板中的单选字段,如 [文档](https://docs.djangoproject.com/en/3.1/ref/forms/widgets/#radioselect) 中所述 (3认同)