【问题标题】:Django template: check for empty query setDjango模板:检查空查询集
【发布时间】:2013-06-30 09:21:36
【问题描述】:

有没有办法检查 Django 模板中的空查询集?在下面的示例中,我只希望在有注释时显示 NOTES 标题。

如果我将 {% empty %} 放在 "for" 中,那么它会显示空标签内的任何内容,因此它知道它是空的。

我希望得到不涉及两次运行查询的东西。

{% if notes - want something here that works %}
     NOTES:
     {% for note in notes %}
         {{note.text}}  
     {% endfor  %}
{% endif  %}

澄清:上面的示例“if notes”不起作用 - 即使查询集为空,它仍会显示标题。

这是视图的简化版本

sql = "select * from app_notes, app_trips where"
notes = trip_notes.objects.raw(sql,(user_id,))

return render_to_response(template, {"notes":notes},context_instance=RequestContext(request))  

编辑:视图选择从多个表中选择。

【问题讨论】:

  • 您确定它会运行两次查询吗?而且,一个简单的建议是“缓存”,但它不能回答您的问题。
  • 我的问题不在于它运行了两次查询。我的例子不起作用。即使查询集为空,它也会显示标题。
  • 请发表您的看法
  • 为什么{% if notes %} 不起作用?
  • notes 是一个原始查询集,与常规查询集不同,它没有定义 __nonzero__ 方法。因此,即使为空,它们也会评估为 True。 docs.python.org/2/reference/datamodel.html#object.__nonzero__

标签: django django-templates


【解决方案1】:

怎么样:

{% if notes != None %}
    {% if notes %}
        NOTES:
        {% for note in notes %}
            {{ note.text }}  
        {% endfor  %}
    {% endif %}
{% else %}
    NO NOTES AT ALL
{% endif %}

【讨论】:

  • 不。它仍然打印标题(但没有注释)
【解决方案2】:

在您的视图中检查notes 是否为空。如果是,则改为传递None

{"notes": None}

在您的模板中,您照常使用{% if notes %}

【讨论】:

  • 这需要运行两次,不是吗?
  • 什么?为什么?您应该将查询分配给变量notes,然后执行{"notes": notes if len(notes) else None} 之类的操作,然后您可以像Simeon 建议的那样检查模板中的notes 是否为None。这是执行此操作的正确方法。
  • 我认为最好是 notes.count() - 最后我检查了 len(notes) 从数据库中提取每条记录,而 count 只是发出一个计数查询。
【解决方案3】:

很遗憾,您无法使用原始查询集 - 它们缺少很多有用的行为。

您可以将原始查询集转换为视图中的列表:

notes_as_list = list(notes)
return render_to_response(template, {"notes":notes_as_list},context_instance=RequestContext(request))

然后在模板中将其检查为布尔值:

{% if notes %}
    Header
    {% for note in notes %}
        {{ note.text }}
    {% endfor %}
{% endif %}

您也可以使用forloop.first 实现这一目标而无需转换:

{% for note in notes %}
    {% if forloop.first %}
         Header
    {% endif %}
    {{ note.text }}
{% endfor %}

【讨论】:

  • forloop.first 对我有用。不错的黑客。另一个没有。它列出了查询本身的所有字母:R A W Q U E R Y S E L E
  • 是的,我检查了make_list 的源代码,但忽略了它已注册为stringfilter,这意味着它会将参数转换为Unicode 对象(如果还没有的话)。我会更新我的答案。
【解决方案4】:

试试{% if notes.all %}。它对我有用。

【讨论】:

  • 也适用于我,我更喜欢这个而不是.count,因为这会发出一个select count(*) 查询,而我认为这会缓存查询集(如果有的话)。
  • 不要使用查询集作为布尔值:而不是if queryset: 使用if queryset.exists(): 请记住,查询集是惰性的,如果您使用查询集作为布尔值,对数据库的不适当查询将进行。 @Chris 方法更好
  • 感谢@KishorPawar 的解决方案,尽管在模板中它没有括号:if queryset.exists
  • @KishorPawar 可以使用 if queryset: ,因为 QuerySet 类覆盖了 __bool__ 魔术方法。见github.com/django/django/blob/…
  • 是的,它是@RuneKaagaard。虽然文档说使用exists()。请参阅bool() 的说明。 docs.djangoproject.com/en/3.2/ref/models/querysets/…
【解决方案5】:

你原来的解决方案

{% if notes %}
    Header
    {% for note in notes %}
        {{ note.text }}
    {% endfor %}
{% endif %}

现在可以与 Django 1.7 一起使用,并且由于 QuerySet 缓存,它不需要成本和额外的查询。

【讨论】:

    【解决方案6】:

    看看 {% empty %} 标签。 文档中的示例

    <ul>
    {% for athlete in athlete_list %}
        <li>{{ athlete.name }}</li>
    {% empty %}
        <li>Sorry, no athletes in this list.</li>
    {% endfor %}
    </ul>
    

    链接:https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty

    【讨论】:

    • 虽然非常有用,但实际上并不能回答问题。 empty 将在没有元素时运行一次。在问题中,OP 希望在列表中有 are 元素时显示文本。 (但只有一次)
    【解决方案7】:

    通常正确的方法是使用{% with ... %} 标签。这会缓存查询,因此它只运行一次,并且与使用 {% empty %} 相比,还为您提供了更大的标记灵活性。

    {% with notes as my_notes %}
    {% if my_notes %}
    <ul>
      {% for note in my_notes %}
      <li>{{ note }}</li>
      {% endfor %}
    </ul>
    {% else %}
    <p>Sorry, no notes available</p>
    {% endif %}
    {% endwith %}
    

    对于这个特定的示例,我不确定它有多大用处,但如果您查询的是多对多字段,例如,这很可能是您想要做的。

    【讨论】:

      【解决方案8】:

      在 django 模板中使用 {% empty %}

      {% if list_data %}
          {% for data in list_data %}
              {{ data.field_1 }}
          {% endfor %}
      {% else %}
          <p>No data found!</p>
      {% endif %}
      

      我们可以用 {% empty %} 编写上面的代码。

      {% for data in list_data %}
          {{ data.field_1 }}
      {% empty %}
          <p>No data found!</p>
      {% endfor %}
      

      【讨论】:

        猜你喜欢
        • 2012-04-14
        • 2010-11-26
        • 2018-12-20
        • 1970-01-01
        • 2020-09-20
        • 1970-01-01
        • 2023-04-11
        • 2020-08-27
        • 1970-01-01
        相关资源
        最近更新 更多