You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Crispy-forms将单选按钮按日期分组并复用ChoiceField?

可以用同一个ChoiceField实现按日期分组的单选按钮(结合Crispy-forms)

完全可以做到,核心思路是利用Django ChoiceField的分组选项结构,配合Crispy-forms的自定义模板来渲染分组效果。以下是具体实现步骤:

1. 构造带分组的ChoiceField选项

先定义按日期分组的时间段选项,外层元组的第一个元素是分组名称(日期),第二个元素是该日期下的所有时间段选项:

TIME_SLOTS = (
    ('2024-05-20', (
        ('slot_may20_09', '9:00-10:00'),
        ('slot_may20_10', '10:30-11:30'),
    )),
    ('2024-05-21', (
        ('slot_may21_14', '14:00-15:00'),
        ('slot_may21_15', '15:30-16:30'),
    )),
)

2. 定义Django表单并配置Crispy-forms

在表单里用单个ChoiceField,指定widget为RadioSelect(单选按钮),然后通过Crispy-forms的自定义模板来处理分组渲染:

from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, Radio

class MeetingScheduleForm(forms.Form):
    time_slot = forms.ChoiceField(
        choices=TIME_SLOTS,
        widget=forms.RadioSelect,
        label="选择会议时间段"
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        # 用自定义模板渲染单选按钮
        self.helper.layout = Layout(
            Fieldset(
                '会议时间段选择',
                Radio('time_slot', template='crispy_custom_radio.html')
            )
        )

3. 编写Crispy-forms自定义Radio模板

创建一个crispy_custom_radio.html模板(放在你的Django模板目录下),遍历分组选项并按日期渲染:

{% load crispy_forms_filters %}
{% load l10n %}

{% for group_name, group_options in field.field.choices %}
    <h5 class="mt-3">{{ group_name }}</h5>
    {% for option_value, option_label in group_options %}
        <div class="form-check">
            <input 
                type="radio" 
                name="{{ field.name }}" 
                id="{{ field.id_for_label }}_{{ option_value }}" 
                value="{{ option_value|unlocalize }}" 
                {% if option_value|stringformat:"s" == field.value|stringformat:"s" %}checked{% endif %} 
                class="form-check-input"
            >
            <label class="form-check-label" for="{{ field.id_for_label }}_{{ option_value }}">
                {{ option_label }}
            </label>
        </div>
    {% endfor %}
{% endfor %}

关键说明

  • 单个ChoiceField就能实现所有单选按钮的分组,提交表单后只会返回选中的时间段值,符合单选逻辑
  • Django的ChoiceField原生支持分组选项结构,Crispy-forms只是需要自定义模板来识别并渲染分组
  • 如果需要动态生成时间段(比如从数据库读取日期和对应时段),只需在表单__init__方法里动态构建带分组的choices即可

内容的提问来源于stack exchange,提问作者Klem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:20:25