Django表单ModelMultipleChoiceField如何正确显示选项标签
问题原因
你当前的异常是因为ModelMultipleChoiceField默认会调用传入模型实例的__str__方法作为选项展示文本,你用values_list('time_slot', flat = True)返回的是时间段编码(如0、1、2)的可迭代对象,没有和你预定义的TIMESLOT_CHOICES做映射,自然只能显示编码本身。
解决方案
优先选用更适配场景的MultipleChoiceField,修改后代码如下:
# 引入你提前定义的TIMESLOT_CHOICES from your_config_file import TIMESLOT_CHOICES class MakeAnAppointmentForm(forms.Form): time_slot = forms.MultipleChoiceField( choices=TIMESLOT_CHOICES, widget=forms.CheckboxSelectMultiple(), label="date" ) def __init__(self,*args,**kwargs): date = kwargs.pop('date') super().__init__(*args,**kwargs) # 查询当前日期可选的时间段编码 available_slot_codes = Appointment.objects.filter(date=date).values_list('time_slot', flat=True) # 过滤出仅允许选择的选项,保留编码和可读时间段的对应关系 self.fields['time_slot'].choices = [ item for item in TIMESLOT_CHOICES if item[0] in available_slot_codes ]
如果业务需要必须使用ModelMultipleChoiceField,可以通过重写label_from_instance方法自定义选项展示文本:
class MakeAnAppointmentForm(forms.Form): time_slot = forms.ModelMultipleChoiceField( queryset = None, widget=forms.CheckboxSelectMultiple(), label="date" ) def __init__(self,*args,**kwargs): from your_config_file import TIMESLOT_CHOICES date = kwargs.pop('date') super().__init__(*args,**kwargs) # 此处不要使用values_list,需返回完整的Appointment模型实例 self.fields['time_slot'].queryset = Appointment.objects.filter(date = date) # 建立编码和可读文本的映射关系 slot_map = dict(TIMESLOT_CHOICES) # 自定义每个选项的展示文本 self.fields['time_slot'].label_from_instance = lambda obj: slot_map.get(obj.time_slot, obj.time_slot)
注意事项
- 第一种方案性能更优,不需要返回完整的模型实例,适合仅需要时间段编码作为提交值的场景。
- 第二种方案适合后续需要对选中的Appointment实例做其他操作的场景。
内容的提问来源于stack exchange,提问作者anthonya
相关产品推荐
相关产品推荐

