【问题标题】:Django template tags: set .active on the first element of a forloop that satisfies a condition [duplicate]Django模板标签:在满足条件的for循环的第一个元素上设置.active [重复]
【发布时间】:2012-09-09 14:37:07
【问题描述】:

我遇到以下问题:用户正在我的网站上学习课程。一门课程由几个章节组成,每章包含几个步骤。如果用户已登录并完成一个步骤,则后端会保存进度。当用户回到站点时,我希望他从他离开的地方继续。为此,我必须将 css 类“活动”添加到相应的导航步骤和每章的内容选项卡中。我的出发点是使用 if 语句测试用户是否已经完成了该步骤。效果很好,但将 .active 添加到所有尚未完成的步骤。我只想将它添加到尚未完成的第一步。我实际上已经解决了这个问题,但这是一个相当粗暴的 hack,我必须包含一个 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 %}

我知道这也可以通过将列表或字典传递给包含所有活动步骤的模板来完成,然后在模板中测试一个步骤是否在该列表中。但这意味着要重写很多视图代码,所以我决定完全在模板中完成。

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

【问题讨论】:

    标签: django for-loop django-templates


    【解决方案1】:

    我知道您已经解决了您的问题,为了完成,我正在发布另一个答案。

    如果您需要在{% for %}{% endfor %} 中通过将当前向导步骤与循环中的当前项目进行匹配来设置类,您可以使用以下代码:

    {% for step in wizard.steps.all %}
        <li class="{% if wizard.steps.step1 == forloop.counter %}active{% elif wizard.steps.step1 > forloop.counter %} complete{% endif %}">
              <span class="step">{{ forloop.counter }}</span>
        </li>
     {% endfor %}
    

    【讨论】:

      【解决方案2】:

      给 Step 添加一个方法:

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

      在模板中:

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

      我们已经在模型中提供了 get_absolute_url 等方便的助手,为什么不添加这个呢?

      如果你不喜欢它,你可以做一个模板过滤器并像这样使用它:

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

      更新

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

      @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 %}
      

      【讨论】:

      • 我喜欢这种方法!但这是否意味着我必须运行其他查询来检查哪个步骤是活动步骤?我已经使用了几个属性伪方法,它们往往非常昂贵。除非我实际上将当前步骤保存在后端,这听起来有点矫枉过正。但我会尝试这两种方法,看看它们有多贵!
      • 更新:添加了另一种方法,它与您在模板中所做的完全一样,但没有您试图摆脱的 hack。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      相关资源
      最近更新 更多