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动作时才会获取数据,导致页面首次加载时没有任何时段选项。
修复:
- 调整
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
- 在视图函数初始化时加载所有时段:
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中的表单按钮,添加两个区分动作的按钮:
- 在日期输入框所在的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>
- 修改原有的预约提交按钮,添加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
相关产品推荐
相关产品推荐

