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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:38:11