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

如何让Django ModelForm接受'%I:%M %p'格式的时间输入?

Django表单时间格式验证问题解决方法

问题描述

我在验证Django表单时遇到问题,表单代码如下:

class reservaForm(forms.ModelForm):
    class Meta:
        model = Reservas
        fields = '__all__'
        widgets = {
            'guests': forms.NumberInput(attrs={'id':'id_invitados','min':'0','class':'form-control form-control-solid'}),
            'date': forms.TextInput(attrs={'id':'date','class':'form-control form-control-solid flatpickr-input'}),
            'timestarts': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_starts','type':'time','class':'form-control form-control-solid','readonly':'readonly','onchange':'ajustarHora()'}),
            'timeends': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_ends','type':'time','class':'form-control form-control-solid','readonly':'readonly'}),
        }

使用JavaScript日历组件实现UI后,提交表单时出现错误:

hora_inicio
Enter a valid time.

表单提交的时间值为'5:30 PM',但无法被识别为有效格式。

解决方法

1. 移除原生时间输入类型冲突

浏览器的type='time'属性会强制使用24小时制的原生时间输入格式,和JS组件返回的12小时带AM/PM的格式冲突。需要移除widget中的type='time'属性:

'timestarts': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_starts','class':'form-control form-control-solid','readonly':'readonly','onchange':'ajustarHora()'}),
'timeends': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_ends','class':'form-control form-control-solid','readonly':'readonly'}),

2. 配置Django时间字段支持12小时格式

Django默认的TimeField只识别24小时制格式(如17:30),需要明确指定支持12小时带AM/PM的格式。在表单类中添加初始化方法:

class reservaForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 让字段同时支持12小时制和24小时制格式
        self.fields['timestarts'].input_formats = ['%I:%M %p', '%H:%M']
        self.fields['timeends'].input_formats = ['%I:%M %p', '%H:%M']
    
    class Meta:
        model = Reservas
        fields = '__all__'
        widgets = {
            'guests': forms.NumberInput(attrs={'id':'id_invitados','min':'0','class':'form-control form-control-solid'}),
            'date': forms.TextInput(attrs={'id':'date','class':'form-control form-control-solid flatpickr-input'}),
            'timestarts': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_starts','class':'form-control form-control-solid','readonly':'readonly','onchange':'ajustarHora()'}),
            'timeends': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_ends','class':'form-control form-control-solid','readonly':'readonly'}),
        }

3. 自定义验证(可选)

如果需要更灵活的验证逻辑,可以重写表单的clean方法:

from datetime import datetime

class reservaForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['timestarts'].input_formats = ['%I:%M %p', '%H:%M']
        self.fields['timeends'].input_formats = ['%I:%M %p', '%H:%M']
    
    class Meta:
        model = Reservas
        fields = '__all__'
        widgets = {
            'guests': forms.NumberInput(attrs={'id':'id_invitados','min':'0','class':'form-control form-control-solid'}),
            'date': forms.TextInput(attrs={'id':'date','class':'form-control form-control-solid flatpickr-input'}),
            'timestarts': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_starts','class':'form-control form-control-solid','readonly':'readonly','onchange':'ajustarHora()'}),
            'timeends': forms.TimeInput(format='%I:%M %p',attrs={'id':'id_time_ends','class':'form-control form-control-solid','readonly':'readonly'}),
        }
    
    def clean_timestarts(self):
        time_str = self.cleaned_data.get('timestarts')
        if not time_str:
            return time_str
        try:
            return datetime.strptime(time_str, '%I:%M %p').time()
        except ValueError:
            try:
                return datetime.strptime(time_str, '%H:%M').time()
            except ValueError:
                raise forms.ValidationError("请输入有效的时间格式,如'5:30 PM'或'17:30'")
    
    def clean_timeends(self):
        time_str = self.cleaned_data.get('timeends')
        if not time_str:
            return time_str
        try:
            return datetime.strptime(time_str, '%I:%M %p').time()
        except ValueError:
            try:
                return datetime.strptime(time_str, '%H:%M').time()
            except ValueError:
                raise forms.ValidationError("请输入有效的时间格式,如'5:30 PM'或'17:30'")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:15:35