2017-03-08 64 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個結果,因爲代碼看起來很明顯。 –