2017-03-08 63 views
0

在一个模板中,我显示了一个项目(i)的前5个翻译。以下逻辑模板处理:模板构造...它的工作原理,但感觉很难看

  • 如果有超过5名翻译:我修剪列表并显示一个 链接more...
  • 如果有1到5个译文:我只是给他们看。
  • 如果没有翻译:我显示添加翻译的链接。

这里是我想出了(功能)模板代码:

{% if i.translation_set.all %} 
    <ul> 
    {% for t in i.translation_set.all|slice:"6" %} 
     {% if forloop.counter < 6 %} 
     <li> 
      <a href="#"> 
       <i class="fa fa-play mr-2"></i> 
       {{ t.language }} 
       <i class="fa fa-commenting-o ml-1"></i> 
      </a> 
     </li> 
     {% else %} 
      <li>more...</li> 
     {% endif %} 
    {% endfor %} 
    </ul> 
{% else %} 
    <a href="{% url 'view-item' i_id=i.id slug=i.slug %}">Add translation</a> 
{% endif %} 

这里是我的关于这段代码的担忧:

if i.translation_set.all执行什么样的查询
  • ?它是查询所有翻译还是停在1?
  • 使用相同的slice查询可能会更好,因为它稍后会被使用,并且可能会自动被缓存?
  • 查询6个项目感觉很难看,只需要显示最大值5。是否有另一种方式来告诉有超过5个项目?

回答

3
{% if i.translation_set.all %} 

如果不通过查询集循环后,那么你应该避免做{% if i.translation_set.all %},因为它会获取所有从数据库中的翻译。改进将使用exists来代替。

{% if i.translation_set.exists %} 

更好的是,您可以使用{% with tag %}来获取切片查询集。然后你可以在if语句中使用切片查询集并循环它。

{% with translations=i.translation_set.all|slice:"6" %} 
{% if translations %} 
<ul> 
    {% for t in translations %} 
    ... 
    {% endfor %} 
</ul> 
... 
{% endif %} 
{% endwith %} 

在片段中提取6个对象的替代方法是将计数作为单独的查询提取。然后,您可以将切片限制为5个对象。

{% with translation_count=i.translation_set.count %} 
{% if translations_count %} 
<ul> 
    {% for t in translations|slice:"5" %} 
    ... 
    {% endfor %} 
    {% if t.count > 5 %} 
     <li>more...</li> 
    {% endif %} 
</ul> 
... 
{% endif %} 
{% endwith %} 

这使用两个查询而不是一个,但如果您发现它更清楚,您可能更喜欢它。在实践中,额外的查询可能对性能没有影响。

+0

为什么'{%with%}'标记比直接的{%for%}'循环更好地被视为(在这种情况下)?编辑:我现在看到,你也可以在'{%if%}'中使用它。是否为更清晰的代码,是的。 –

+0

准确地说 - 通过使用'{%with%}'标记,您可以在'{%if%}'标记中使用queryset并循环它,并且只会从数据库中提取一次。 – Alasdair

+0

是的,我实际上试图弄清楚如何将查询集存储在变量中。看起来像这样优雅地解决它。我决定去取6个结果,因为代码看起来很明显。 –