如何在Django表单校验中通过ValidationError返回可用预约时段列表
实现方案
只需要修改forms.py中BookingForm的clean校验方法即可,具体修改逻辑如下:
- 先获取用户提交的配送日期、配送时间,若两个字段未通过基础校验(比如用户未填写)则直接返回校验结果
- 查询该配送日期下所有已预约记录的时段小时数
- 用全量可选时段(7-12点)减去已预约时段,得到可用时段列表并格式化
- 若用户选择的时段已被占用,将可用时段拼入错误提示抛出即可
修改后的完整BookingForm代码如下:
from django import forms from bookmyslot.models import Booking,Customer from bootstrap_datepicker_plus import DatePickerInput import datetime as dt from django.utils import timezone HOUR_CHOICES = [(dt.time(hour=x), '{:02d}:00'.format(x)) for x in range(7, 13)] class BookingForm(forms.ModelForm): def __init__(self,*args,**kwargs): user = kwargs.pop('username',None) super(BookingForm,self).__init__(*args,**kwargs) self.fields['qty_plts'].label = "Quantity Of Pallets" self.fields['cbm'].label = "Shipment CBM" self.fields['delivery_date'].label = "Delivery Date" self.fields['delivery_time'].label = "Delivery Time" self.fields['customer_name'].label = "Customer Name" self.fields['customer_name'].queryset = Customer.objects.filter(username=user) def clean(self): cleaned_data = super(BookingForm,self).clean() delivery_date = cleaned_data.get('delivery_date') delivery_time = cleaned_data.get('delivery_time') # 字段未通过基础校验直接返回 if not delivery_date or not delivery_time: return cleaned_data # 查询当前日期已预约的小时列表 booked_hours = Booking.objects.filter( delivery_date=delivery_date ).values_list('delivery_time__hour', flat=True) # 计算可用时段 free_hours = sorted(set(range(7,13)) - set(booked_hours)) # 可选优化:判断当日是否还有可用时段 if not free_hours: raise forms.ValidationError("该日期所有时段均已约满,请选择其他日期") free_slot_str = "、".join([f"{h:02d}:00" for h in free_hours]) # 校验当前时段是否已被占用 if delivery_time.hour in booked_hours: raise forms.ValidationError(f"请求时段已被预约,请从以下可用时段中选择:{free_slot_str}") return cleaned_data class Meta: model = Booking fields = ('customer_name','qty_plts','cbm','delivery_date','delivery_time') widgets = {'delivery_date':DatePickerInput(options={"daysOfWeekDisabled":[0,6],"minDate":timezone.now().date().strftime('%Y-%m-%d')}), 'delivery_time':forms.Select(choices=HOUR_CHOICES)}
修改完成后无需调整models、views层代码,用户提交已被占用的时段时,就会自动返回包含可用时段的错误提示。
内容的提问来源于stack exchange,提问作者logicpro
相关产品推荐
相关产品推荐

