Django如何查询指定日期预约并实现当月预约按日期排列展示
功能实现方案
后端视图代码完善
首先修正你原有代码的变量命名冲突问题,补充预约查询、按日期分组的逻辑,完整代码如下:
import calendar from datetime import datetime from django.utils import timezone from .models import Appointment def monthly_appointment(request): today = timezone.localdate() # 用时区适配的本地日期 year = today.year month = today.month # 获取当月所有日期 num_days = calendar.monthrange(year, month)[1] date_list = [datetime.date(year, month, day) for day in range(1, num_days+1)] # 格式化日期(包含星期),同时保留原始日期对象用于匹配预约 formatted_dates = [] for d in date_list: formatted_dates.append({ 'date_obj': d, 'display_str': d.strftime('%A, %d') # 格式如 Monday, 05 }) # 查询当月所有预约 month_start = datetime.date(year, month, 1) month_end = datetime.date(year, month, num_days) # 按开始时间的日期过滤,注意时区转换 appointments = Appointment.objects.filter( start_appointment__date__gte=month_start, start_appointment__date__lte=month_end ).select_related('user', 'seat') # 预加载关联数据优化性能 # 把预约按日期分组,做成字典 appointment_map = {} for appt in appointments: # 转换为本地日期避免时区偏差 appt_date = timezone.localtime(appt.start_appointment).date() if appt_date not in appointment_map: appointment_map[appt_date] = [] appointment_map[appt_date].append(appt) # 传递数据到模板 context = { 'formatted_dates': formatted_dates, 'appointment_map': appointment_map, 'month_name': calendar.month_name[month] + ' ' + str(year) } return render(request, 'your_template.html', context)
模板渲染实现
在模板文件your_template.html中按日历表格结构渲染,示例代码如下:
<h2>{{ month_name }} 预约日历</h2> <table border="1" cellpadding="10" cellspacing="0"> <tr> {% for date_item in formatted_dates %} <td valign="top" width="14%"> <strong>{{ date_item.display_str }}</strong> <hr> {% with appts=appointment_map|get_item:date_item.date_obj %} {% if appts %} {% for appt in appts %} <div> <p>时间: {{ appt.start_appointment|time:"H:i" }} - {{ appt.end_appointment|time:"H:i" }}</p> <p>用户: {{ appt.user.username }}</p> <p>座位: {{ appt.seat.seat_name|default:"已取消" }}</p> </div> <hr> {% endfor %} {% else %} <p>*暂无预约*</p> {% endif %} {% endwith %} </td> <!-- 每7个日期换一行,对应一周7天 --> {% if forloop.counter|divisibleby:7 %} </tr><tr> {% endif %} {% endfor %} </tr> </table>
注意:如果模板不支持
get_item过滤器,你可以自定义一个简单的模板过滤器,或者在后端组装formatted_dates的时候直接把对应预约塞到每个date_item里。
额外优化建议
- 日期换行逻辑如果需要适配周一为一周起始,可以调整
calendar.monthrange的返回值来处理首行的空白占位 - 可以给不同状态的预约加不同的样式区分,比如已过期、未开始的预约用不同颜色标注
- 如需支持切换月份,只需要把前端传递的年月参数替换掉代码里的today取值即可
内容的提问来源于stack exchange,提问作者paniklas
相关产品推荐
相关产品推荐

