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

Django预约系统时段不显示问题排查求助

Django预约系统时段不显示问题排查与修复

核心问题1:模板变量名不匹配

视图函数book_appointment传递给模板的上下文变量是available_timeslots,但模板中循环遍历的变量名是timeslots,导致模板无法获取任何时段数据。

修复:
修改appointment.html中的循环代码:

{% for timeslot, available in available_timeslots %}
    <option value="{{ timeslot.id }}" {% if not available %}disabled{% endif %}>
        {{ timeslot.slot_text }} {% if not available %}(booked){% endif %}
    </option>
{% endfor %}

核心问题2:GET请求初始状态无时段数据

视图中默认available_timeslots为空列表,只有在POST请求触发check_timeslots动作时才会获取数据,导致页面首次加载时没有任何时段选项。

修复:

  1. 调整check_availability函数,支持无日期参数时返回所有可用时段:
from datetime import datetime

def check_availability(date_str=None):
    timeslots = Timeslot.objects.all()
    booked_timeslots = []
    if date_str:
        try:
            # 将POST获取的日期字符串转为date对象
            date = datetime.strptime(date_str, '%Y-%m-%d').date()
            booked_timeslots = Appointment.objects.filter(date=date).values_list('timeslot', flat=True)
        except ValueError:
            # 日期格式错误时,默认所有时段可用
            pass
    # 生成(时段对象, 是否可用)的列表
    available_timeslots = [(timeslot, timeslot.id not in booked_timeslots) for timeslot in timeslots]
    return available_timeslots
  1. 在视图函数初始化时加载所有时段:
def book_appointment(request):
    # GET请求时默认加载所有时段
    available_timeslots = check_availability()
    form_data = {}
    if request.method == 'POST':
        # 原有POST逻辑保持不变,仅需将date参数改为date_str传递给check_availability
        name = request.POST.get('name')
        phone = request.POST.get('phone')
        email = request.POST.get('email')
        date_str = request.POST.get('date')
        timeslot_id = request.POST.get('timeslot')

        form_data = {
            'name': name,
            'phone': phone,
            'email': email,
            'date': date_str,
            'timeslot': timeslot_id,
        }

        if 'check_timeslots' in request.POST:
            if date_str:
                available_timeslots = check_availability(date_str)
            else:
                messages.error(request, '请选择日期以检查可用时段。')
        elif 'book_appointment' in request.POST:
            if not all([name, phone, email, date_str, timeslot_id]):
                messages.error(request, '请填写所有必填字段。')
            else:
                try:
                    date = datetime.strptime(date_str, '%Y-%m-%d').date()
                    timeslot = Timeslot.objects.get(id=timeslot_id)
                    existing_appointment = Appointment.objects.filter(date=date, timeslot=timeslot).exists()
                    if existing_appointment:
                        messages.error(request, '该时段已被预订。')
                        available_timeslots = check_availability(date_str)
                    else:
                        appointment = Appointment.objects.create(
                            name=name,
                            phone=phone,
                            email=email,
                            date=date,
                            timeslot=timeslot
                        )

                        send_mail(
                            subject="预约确认",
                            message=f"亲爱的{name}:\n\n您的预约已确认,时间为{date} {timeslot.slot_text}。\n\n感谢您的预约!",
                            from_email='your-email@example.com',
                            recipient_list=[email, 'your-email@example.com'],
                            fail_silently=False,
                        )

                        messages.success(request, '预约成功!')
                        return redirect('appointment')
                except ValueError:
                    messages.error(request, '日期格式错误,请选择正确的日期。')
                    available_timeslots = check_availability()
                except Timeslot.DoesNotExist:
                    messages.error(request, '所选时段不存在。')
                    available_timeslots = check_availability(date_str)

    return render(request, 'appointment/appointment.html', {
        'available_timeslots': available_timeslots,
        'form_data': form_data,
    })

核心问题3:表单无区分动作的按钮

当前表单只有一个提交按钮,无法触发check_timeslots动作,导致用户选择日期后无法更新时段的可用状态。

修复:
修改appointment.html中的表单按钮,添加两个区分动作的按钮:

  1. 在日期输入框所在的div中添加“检查可用时段”按钮:
<div class="col-lg-6">
    <div class="appoinment-form-input">
        <input type="date" class="doctor-name wide mb-30" name="date" required value="{{ form_data.date }}">
        <button type="submit" name="check_timeslots" class="tp-btn btn-sm">检查可用时段</button>
    </div>
</div>
  1. 修改原有的预约提交按钮,添加name属性:
<button type="submit" name="book_appointment" class="tp-btn">确认预约</button>

额外优化:表单数据回显

为了提升用户体验,将用户已填写的表单数据回显到输入框中,修改各输入框的value属性:

<input type="text" name="name" placeholder="Your Name" required value="{{ form_data.name }}">
<input type="text" name="phone" placeholder="Phone" required value="{{ form_data.phone }}">
<input type="email" name="email" placeholder="Email Address" required value="{{ form_data.email }}">
<select class="doctor-name wide mb-30" name="timeslot" required>
    <option value="">Select TimeSlot</option>
    {% for timeslot, available in available_timeslots %}
        <option value="{{ timeslot.id }}" {% if timeslot.id|stringformat:"s" == form_data.timeslot and available %}selected{% endif %} {% if not available %}disabled{% endif %}>
            {{ timeslot.slot_text }} {% if not available %}(booked){% endif %}
        </option>
    {% endfor %}
</select>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:18:11