基于Django Forms的牙医预约系统:动态时段显示问题排查
Django牙医预约表单动态时段加载问题解决方案
你的问题在于仅靠后端表单初始化逻辑无法实现前端动态更新时段——当前代码只有在表单提交(POST请求)时才会根据提交的日期过滤时段,但用户在前端选择日期后,没有触发任何请求去后端获取更新后的可用时段,所以time_slot字段要么显示初始全部选项(首次加载),要么在提交后才更新,无法实现实时动态效果。
以下是分步解决方法:
1. 新增后端AJAX接口返回可用时段
在views.py中添加处理AJAX请求的视图,接收日期参数并返回该日期的可用时段:
from django.http import JsonResponse from .models import Appointment def get_available_time_slots(request): if request.method == 'GET' and 'date' in request.GET: selected_date = request.GET.get('date') booked_slots = Appointment.objects.filter(date=selected_date).values_list('time_slot', flat=True) all_slots = [ '09:00 AM', '10:00 AM', '11:00 AM', '12:00 PM', '02:00 PM', '03:00 PM', '04:00 PM', '05:00 PM', '06:00 PM', '07:00 PM', ] available_slots = [slot for slot in all_slots if slot not in booked_slots] # 构造下拉框选项格式 options = [{'value': '', 'text': 'Select Time Slot'}] + [{'value': slot, 'text': slot} for slot in available_slots] return JsonResponse({'options': options}) return JsonResponse({'options': []})
在urls.py中添加对应路由:
from django.urls import path from . import views urlpatterns = [ # 现有路由... path('get-available-slots/', views.get_available_time_slots, name='get_available_slots'), ]
2. 前端添加JS监听日期变化并更新时段
在表单模板末尾添加JavaScript,监听日期选择事件,通过AJAX请求更新时段下拉框:
<script> document.addEventListener('DOMContentLoaded', function() { const dateInput = document.getElementById('{{ appointment_form.date.id_for_label }}'); const timeSlotSelect = document.getElementById('{{ appointment_form.time_slot.id_for_label }}'); // 页面加载时若已有选中日期,自动更新时段 if (dateInput.value) { updateTimeSlots(dateInput.value); } // 监听日期选择变化 dateInput.addEventListener('change', function() { updateTimeSlots(this.value); }); function updateTimeSlots(date) { fetch(`{% url 'get_available_slots' %}?date=${date}`) .then(response => response.json()) .then(data => { timeSlotSelect.innerHTML = ''; data.options.forEach(option => { const opt = document.createElement('option'); opt.value = option.value; opt.textContent = option.text; timeSlotSelect.appendChild(opt); }); }) .catch(error => { console.error('加载时段失败:', error); timeSlotSelect.innerHTML = '<option value="">Select Time Slot</option>'; }); } }); </script>
3. 修复表单初始化与添加后端验证
调整表单__init__方法兼容GET/POST请求,并添加表单验证防止提交已预约时段:
class AppointmentForm(forms.Form): # 现有字段定义... def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 绑定表单时(POST请求)处理日期 if self.is_bound: selected_date = self.cleaned_data.get('date') or self.data.get('date') if selected_date: booked_appointments = Appointment.objects.filter(date=selected_date).values_list('time_slot', flat=True) all_time_slots = [ '09:00 AM', '10:00 AM', '11:00 AM', '12:00 PM', '02:00 PM', '03:00 PM', '04:00 PM', '05:00 PM', '06:00 PM', '07:00 PM', ] available_time_slots = [slot for slot in all_time_slots if slot not in booked_appointments] self.fields['time_slot'].choices = [('', 'Select Time Slot')] + [(slot, slot) for slot in available_time_slots] def clean(self): cleaned_data = super().clean() date = cleaned_data.get('date') time_slot = cleaned_data.get('time_slot') if date and time_slot: if Appointment.objects.filter(date=date, time_slot=time_slot).exists(): self.add_error('time_slot', '该时段已被预约,请选择其他时段。') return cleaned_data
4. 数据库层添加唯一约束(可选但推荐)
在Appointment模型中添加联合唯一约束,从数据库层面杜绝重复预约:
class Appointment(models.Model): # 现有字段定义... class Meta: unique_together = ('date', 'time_slot')
运行迁移命令生效:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Apoorva Singh Baghel
相关产品推荐
相关产品推荐

