Django模板标签:在满足条件的forloop的第一个元素上设置.active [英] Django template tags: set .active on the first element of a forloop that satisfies a condition

查看:214
本文介绍了Django模板标签:在满足条件的forloop的第一个元素上设置.active的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到以下问题:用户正在我的网站上学习课程。一门课程包含几章,每章包含几个步骤。如果用户已登录并完成步骤,则后端将保存进度。当用户返回该站点时,我希望他在他离开的地方继续。为此,我必须将css类活动添加到相应的导航步骤和每章的内容选项卡中。我的出发点是使用if语句测试用户是否已经完成了该步骤。效果很好,但将.active添加到了尚未完成的所有步骤。我只想将其添加到尚未完成的第一步。我实际上已经解决了这个问题,但这是一个蛮横的破解,我必须添加一个自定义模板标记,允许我在模板中设置变量

I have the following problem: A user is taking a course on my website. A course consists of several chapters and each chapter consists of several steps. If the user is logged in and completes a step, the backend saves the progress. When the user comes back to the site, I want him to continue where he left off. To do this I have to add the css class "active" to the corresponding navigation step and the content tab of each chapter. My starting point was to test with an if statement if the user had already finished the step. That worked great, but adds .active to all the steps that have not been finished yet. I only want to add it to the first step that hasn't been finished yet. I have actually solved this problem but it is a rather brute hack and I had to include a custom template tag that allows me to set a variable in the template:

{% load custom_tags %}

{% for chapter in chapters %}
<div>
    <ul class="unstyled wizard clearfix">
        {% set active_wizard_steps = 0 %}
        {% for step in chapter.steps.all %}
        <li class="{% if not step.read and active_wizard_steps == 0 %}active{% set active_wizard_steps = 1 %}{% endif %}{% if step.read %} finished{% endif %}"></li>
        {% endfor %}
    </ul>
</div>
{% endfor %}

我知道也可以通过传递列表来完成或使用所有活动步骤指定模板,然后在模板中测试该列表中是否包含步骤。但这将意味着重写大量视图代码,因此我决定在模板中完全这样做。

I know that this can also be done by passing a list or dict to the template with all the active steps and then testing in the template if a step is in that list. But that would have meant rewriting a lot of view code so I decided to do it completely in the template.

所以我的问题是:解决此问题的最佳实践方法是什么?我只是出于好奇而问,因为发现这个问题实际上很有趣。

So my question is: what would be the best practice way to solve this problem? I'm asking just out of curiousity and because the problem was actually really fun to figure out. Thanks a lot!

推荐答案

在步骤中添加方法:

class Step(models.Model):
    # ...
    def is_active(self):
        # do your sauce

在模板中:

class="{% if step.is_active %}active{% endif %}"

我们已经在模型中有方便的助手,例如get_absolute_url,为什么不添加它呢?

We already have convenient helpers like get_absolute_url in models, why not add this one ?

如果您不喜欢它,则可以做一个模板过滤器并按如下方式使用它: / p>

If you don't like it, you could do a template filter and use it as such:

class="{% if step|is_active %}active{% endif %}"



更新



这里是另一种方法,请像这样制作模板过滤器:

Update

Here's another method, make a template filter as such:

@register.filter
def set_active_steps(steps):
    active_wizard_steps = 0

    for step in steps:
        if not step.read and active_wizard_steps == 0:
            step.is_active = True

    return steps

然后,在您的模板中:

{% for step in chapter.steps.all|set_active_steps %}
    ... {% if step.is_active %}...{% endif %}
{% endfor %}

这篇关于Django模板标签:在满足条件的forloop的第一个元素上设置.active的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆