Django HTML模板嵌套循环异常:无法按用户预订状态显示对应按钮
问题:已预订会话显示quit按钮,未预订显示book按钮无法实现
需求:登录用户已预订的会话显示'quit'按钮,未预订的会话显示'book'按钮,当前无法实现该功能。
模型代码
class Member(models.Model): gym = models.ForeignKey(Gym, on_delete=models.CASCADE, blank=True, null=True, related_name="gym_membership") member = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True, related_name="member_of_gym") def __str__(self): return f'{self.member.username}' class Session(models.Model): program = models.ForeignKey(Program, on_delete=models.CASCADE, blank=True, null=True, related_name="session_program") focus = models.ForeignKey(Focus, on_delete=models.CASCADE, blank=True, null=True, related_name="session_focus") location = models.ForeignKey(Location, on_delete=models.CASCADE, blank=True, null=True, related_name="session_location") booking_counter = models.IntegerField(default=0) start_datetime: datetime = models.DateTimeField() duration = models.DurationField() day = models.CharField(max_length=12, blank=True, null=True) week_number = models.IntegerField(blank=True, null=True) def __str__(self): return f'{self.program}, {self.day} - Week {self.week_number}' class Booking(models.Model): member = models.ForeignKey(Member, on_delete=models.CASCADE, blank=True, null=True, related_name="member_booking") session = models.ForeignKey(Session, on_delete=models.CASCADE, blank=True, null=True, related_name="booking_session") booking = models.BooleanField() date_booked = models.DateTimeField() date_cancelled = models.DateTimeField(blank=True, null=True) attendance_verified = models.BooleanField(blank=True, null=True) def __str__(self): return f'{self.member.member.username} booked {self.session}'
视图代码
def index(request): # store the user information in a variable user = request.user # get the membership object for that user member = Member.objects.get(member=user.id) context = { "sessions": Session.objects.all(), "bookings": Booking.objects.filter(member=member) } return render(request, "booking/index.html", context)
模板代码(index.html)
{% extends "booking/layout.html" %} {% block body %} {% if user.is_authenticated %} <h2>INTERFACE</h2> <p>WEEK X < ></p> <br> <class class="card"> <div class="card-header"> BOOKINGS </div> <ul class="list-group list-group-flush"> {% for session in sessions %} <li class="list-group-item">{{ session.day }}: <a href="{% url 'session' session.id %}">{{ session.program }} </a> <form class="nav-item ms-auto float-end" action="{% url 'book' session.id %}" method="post"> {% csrf_token %} {# {% for booking in bookings %}#} {% for booking in session.booking_session %} {% if booking.session == session %} <button type="submit" class="btn btn-outline-light ms-auto btn-sm">quit</button> {% else %} <button type="submit" class="btn btn-outline-light ms-auto btn-sm">book</button> {% endif %} {% endfor %} </form> </li> {% endfor %} </ul> </class> {% endif %} {% endblock %}
原实现问题分析
- 模板遍历
session.booking_session会获取该会话的所有预订记录(包含其他用户的),导致按钮判断错误或重复显示 - 未过滤
Booking模型中booking=True的有效预订状态 - 嵌套循环逻辑冗余,无法精准匹配当前用户的预订状态
修改方案
1. 优化视图代码
提前获取当前用户已预订的会话ID集合,减少模板中的数据库查询:
def index(request): user = request.user # 直接传入user对象而非id,符合ORM规范 member = Member.objects.get(member=user) # 获取当前用户的有效预订会话ID集合(过滤booking=True的记录) booked_session_ids = set( Booking.objects.filter(member=member, booking=True) .values_list('session__id', flat=True) ) context = { "sessions": Session.objects.all(), "booked_session_ids": booked_session_ids } return render(request, "booking/index.html", context)
2. 修改模板代码
去掉嵌套循环,直接通过会话ID判断预订状态,同时修正模板标签错误:
{% extends "booking/layout.html" %} {% block body %} {% if user.is_authenticated %} <h2>INTERFACE</h2> <p>WEEK X < ></p> <br> <div class="card"> <div class="card-header"> BOOKINGS </div> <ul class="list-group list-group-flush"> {% for session in sessions %} <li class="list-group-item">{{ session.day }}: <a href="{% url 'session' session.id %}">{{ session.program }} </a> <form class="nav-item ms-auto float-end" action="{% url 'book' session.id %}" method="post"> {% csrf_token %} {% if session.id in booked_session_ids %} <button type="submit" class="btn btn-outline-light ms-auto btn-sm">quit</button> {% else %} <button type="submit" class="btn btn-outline-light ms-auto btn-sm">book</button> {% endif %} </form> </li> {% endfor %} </ul> </div> {% endif %} {% endblock %}
注:原模板中<class class="card">为错误写法,已修正为<div class="card">。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

