为RadioSelect中的每个选项设置help_text

10 投票
4 回答
3629 浏览
提问于 2025-04-15 18:55

我可以在任何表单字段上设置帮助文本,但我想知道是否可以在RadioSelect()的选项上设置帮助文本。

我希望能有一个简单的方法,在每个单选按钮下面显示一些帮助信息。

下面是模型和表单的代码,我可以在模板中渲染名称属性,显示标签、输入元素和帮助文本。我还想能够渲染membership_type属性,带有标签('会员类型')、单选按钮('开放会员'和'封闭会员'),以及与每个单选元素相关的帮助文本('任何人都可以加入这个小组'和'只有特定成员可以加入这个小组')。

class Group(models.Model):
  MEMBERSHIP_CHOICES = (
    ('O', 'Open membership'),
    ('C', 'Closed membership'),
  )

  name = models.CharField(max_length=255)
  membership_type = models.CharField(max_length=1, choices=MEMBERSHIP_CHOICES, default="O")

class GroupForm(forms.ModelForm):
  name = forms.CharField(label="Group name", help_text="Enter a name for your new group")

  class Meta:
    model = Group
    widgets = { "membership_type": forms.RadioSelect }

4 个回答

0

嘿,快到2024年了,你现在可以这样做。

比如,在一个布尔模型的字段里:

models.BooleanField(default=False,help_text="Your help text")

在你的表单里

value = forms.RadioSelect()

页面上的输出看起来正好是你想要的样子。

2

对于那些在10多年后看到这个的人,我是通过创建一个自定义小部件来实现的,这个小部件覆盖了默认的单选按钮模板,并且给它传递了自定义属性。

# Custom widget    
class RadioSelectHelpTextWidget(forms.RadioSelect):
                option_template_name = 'custom_templates/forms/radio_option_help_text.html'
        
# Form class that calls widgets, passed custom attributes to widget
class TemplateCreateForm(ModelForm):
            created_by = forms.ModelChoiceField(required=False,queryset=User.objects.none())
            class Meta:
                model = Template
                fields = ['name', 'type', 'created_by']
                widgets = {
                    'name': forms.TextInput(attrs={'class': 'input'}),
                    'type': RadioSelectHelpTextWidget(
                        attrs={
                            'help_text': {
                                'custom': 'This is custom help text.',
                                'html': 'This is help text for html.'
                            }
                        }
                    )
                }

自定义单选按钮的模板(custom_templates/forms/radio_option_help_text.html)

{% load custom_template_filters %}
{% if widget.wrap_label %}
    <label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>
{% endif %}
{% include "django/forms/widgets/input.html" %}
{% if widget.wrap_label %}
    {{ widget.label }}
    {% if widget.attrs.help_text %}
        {% if widget.value in widget.attrs.help_text %}
            <p class="is-size-7">
             {{ widget.attrs.help_text|dict_get:widget.value }}
            </p>
        {% endif %}
    {% endif %}
    </label>
{% endif %}

结果是这样的: 这里输入图片描述

6

@Rishabh 说得对,但我想进一步解释一下,因为乍一看,这似乎不是解决方案,实际上它是的;或者说,至少可以通过一些小技巧来实现有用的效果,而不需要深入了解 Django 表单。

元组的第二个元素放在 "label" 标签里面,所以任何 '行内元素' 都是可以的;例如:

想要的结果

或者类似的东西

<ul>
  <li><label for="id_ticket_0">
      <input type="radio" id="id_ticket_0" value="PARTTIME" name="ticket"> 
      <em>Part Time</em> Valid on Friday Night and Saturday Only
  </label></li>
  <li><label for="id_ticket_1">
      <input type="radio" id="id_ticket_1" value="DAYTIME" name="ticket"> 
      <em>Casual</em> Valid on Saturday Only
  </label></li>
  <li><label for="id_ticket_2">
       <input type="radio" id="id_ticket_2" value="EARLYBIRD" name="ticket"> 
       <em>Early Bird</em> Valid on Friday, Saturday, and Sunday. $15 discount for booking before 1am January 3rd, 2011
   </label></li>
</ul>

简单示例

诀窍在于将描述的内容“标记为安全”,然后把你需要的东西放进去:

from django.utils.safestring import mark_safe
choices = (
  ('1', mark_safe(u'<em>One</em> | This is the first option. It is awesome')),
  ('2', mark_safe(u'<em>Two</em> | This is the second option. Good too.'))
)

复杂示例

在这个例子中,我们:

  1. 把选项组合成一个列表(任何 可迭代 结构都可以)
  2. 把这个结构传递给表单的 init 方法,以动态创建我们的单选框选项
  3. 使用 列表推导式 为每个单选框选项创建一个扩展描述

数据结构:

  • tickets.code - 就是票据代码
  • label - 简短的描述
  • help - 更详细的描述

但稍后再详细说这个。首先,让我们创建一些实例:

from mymodule import ticket
# so lets create a few
fulltime = ticket('FULLTIME',160,'Full Time',
              "Valid Monday to Friday inclusive")
parttime = ticket('PARTTIME',110,'Full Time',
              "Valid outside of business hours only")
daytime  = ticket('DAYTIME',70,'Day Time',
              "Valid only on weekends and public holidays")

# and put them together in a list any way you like
available_tickets = [fulltime, parttime, daytime]

# now create the form
OrderForm(tickets=available_tickets)

这可能发生在你的 视图 代码中。现在看看 表单 中会发生什么

class OrderForm(ModelForm):

    def __init__(self, *args, **kwargs):
        self.tickets = kwargs.pop('tickets')
        super(OrderForm, self).__init__(*args, **kwargs)

        choices = [(t.code, mark_safe(u'<em>%s</em> %s' % (t.label, t.help)))
                for t in self.tickets]
        self.fields['ticket'] = forms.ChoiceField(
            choices = choices,
            widget  = forms.RadioSelect()
        )

撰写回答