Django HTML模板中的双重嵌套循环没有得到预期的结果

yrwegjxp  于 2023-11-20  发布在  Go
关注(0)|答案(2)|浏览(97)

我已经盯着这一个有一段时间了,需要一些帮助。
我试图在登录用户已预订会话的日子显示“退出”按钮而不是“预订”按钮。有人能在这里提供一些指导吗?

型号

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)

索引. 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 %}


正如您所看到的,我在index.html示例中尝试了嵌套的for循环。我已经两次尝试接近我想要的结果(请参见index.html中的注解行),但都没有用。
我最初的方法是将所有会话作为一个变量生成(以显示所有会话),然后生成当前登录用户的预订列表(该列表显示哪些行的会话需要退出按钮,而不是预订按钮),这对我来说非常有意义。
不过,执行起来有些麻烦,还请帮忙。

t30tvxxf

t30tvxxf1#

感谢@Temi,我有了解决方案。
我不得不对index.html做一些小的额外编辑,以便在按下退出按钮时执行退出视图,对于book按钮也是如此。
我所做的这些修改是我在写原始描述时缺乏细节。

<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>
                    {% if session.has_member_booking %}
                        <form class="nav-item ms-auto float-end" action="{% url 'quit' session.id %}" method="post">
                            {% csrf_token %}
                            <button type="submit" class="btn btn-outline-light ms-auto btn-sm">quit</button>
                        </form>
                    {% else %}
                        <form class="nav-item ms-auto float-end" action="{% url 'book' session.id %}" method="post">
                            {% csrf_token %}
                            <button type="submit" class="btn btn-outline-light ms-auto btn-sm">book</button>
                        </form>
                    {% endif %}
            </li>
        {% endfor %}
    </ul>

字符串
我现在知道了在视图中使用的annotate()函数,所以这是我Django工具箱中的一个新工具。
谢谢@Temi。

nhhxz33t

nhhxz33t2#

建议将大部分应用程序逻辑集中在视图中,避开模板中的复杂操作,以减轻潜在的性能瓶颈。
现在,让我们来解决具体的代码问题。在您当前的实现中,一个逻辑缺陷是显而易见的。内部循环检查是否为booking.session == session,由于您正在迭代session.booking_session{% for booking in session.booking_session %}),因此其计算结果总是True
关于您评论的替代选项,{% for booking in bookings %},这应该可以按预期工作。我建议重新访问这种方法并交叉检查您的数据库,以确保确实有与会话相关的预订。
要获得更健壮的解决方案,请考虑使用Django中的annotate函数,如下面重构的代码片段所示:

from django.db.models import Count, Case, When, IntegerField

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)

    # Use annotate to add a 'has_member_booking' attribute to each session
    sessions = Session.objects.annotate(
        has_member_booking=Count(
            Case(
                When(booking_session__member=member, then=1),
                output_field=IntegerField()
            )
        )
    )

    context = {
        "sessions": sessions,
    }

    return render(request, "booking/index.html", context)

字符串
然后在您的模板中

<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.has_member_booking %}
                    <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>


这不仅解决了性能问题,而且为处理所需的功能提供了一个更优雅、更有效的解决方案。

相关问题