如何基于Booking模型过滤TimeSlot QuerySet并按占用状态渲染至HTML?
正确实现基于占用状态渲染时段的方法
1. 优化数据库查询,解决N+1性能问题
原代码循环中每次调用Booking.objects.get()会触发多次数据库查询,效率极低。可以用Django的Exists子查询结合annotate,一次性为每个TimeSlot标记预订状态:
from django.db.models import Exists, OuterRef def your_view(request): # 获取会话中存储的日期和占用状态过滤条件 check_in_date = request.session.get('date') occupancy_filter = request.session.get('occupancy', '') # 定义子查询:检查当前时段是否已被预订 booked_subquery = Booking.objects.filter( check_in_date=check_in_date, timeslot=OuterRef('pk') ) # 为每个TimeSlot添加is_booked字段,标记是否已预订 time_slots = TimeSlot.objects.select_related('room').annotate( is_booked=Exists(booked_subquery) ) # 根据占用状态过滤时段 if occupancy_filter == 'Vacant': time_slots = time_slots.filter(is_booked=False) elif occupancy_filter == 'Booked': time_slots = time_slots.filter(is_booked=True) # 为空值时显示所有时段 # 将处理好的时段数据传给模板 return render(request, 'your_template.html', {'time_slots': time_slots})
2. 在HTML模板中渲染时段状态
模板中直接根据is_booked字段判断状态,渲染对应内容:
{% for slot in time_slots %} <div class="time-slot-item"> <h4>房间{{ slot.room.number }}({{ slot.room.category }})</h4> <p>时段:{{ slot.available_from }} - {{ slot.available_till }}</p> <p class="status"> 状态:{% if slot.is_booked %} <span style="color:red;">已预订</span> {% else %} <span style="color:green;">空闲</span> {% endif %} </p> <!-- 仅空闲时段显示预订按钮 --> {% if not slot.is_booked %} <button class="book-btn">预订此时段</button> {% endif %} </div> {% endfor %}
3. 修正原逻辑中的核心错误
- 原代码中
time_slot.delete()逻辑错误:TimeSlot是房间的固定时段配置,不应删除,只需通过过滤控制显示内容即可。 - 避免直接给
TimeSlot对象添加临时属性(如occupancy),用annotate生成的字段更高效且符合Django ORM规范。 - 原代码捕获
Exception范围过广,应改为捕获Booking.DoesNotExist,避免隐藏其他异常。
内容的提问来源于stack exchange,提问作者Anshul Gupta
相关产品推荐
相关产品推荐

