如何在Django模板中进行查询过滤

104 投票
8 回答
154836 浏览
提问于 2025-04-11 09:29

我需要在Django模板中进行一个过滤查询,想要得到一组对象,这个过程就像在视图中用Python代码一样:

queryset = Modelclass.objects.filter(somekey=foo)

在我的模板里,我想这样做:

{% for object in data.somekey_set.FILTER %}

但是我就是找不到怎么写FILTER。

8 个回答

15

我经常遇到这个问题,通常会选择“添加一个方法”的解决方案。不过,有些情况下“添加一个方法”或者“在视图中计算”并不奏效(或者效果不好)。比如,当你在缓存模板片段时,需要一些复杂的数据库计算来生成它。你不想在不需要的时候就去做数据库的工作,但你在深入模板逻辑之前并不知道自己是否真的需要。

还有一些其他可能的解决方案:

  1. 使用{% expr <expression> as <var_name> %}这个模板标签,具体可以查看http://www.djangosnippets.org/snippets/9/。这个表达式可以是任何合法的Python表达式,模板的上下文会作为你的本地作用域。

  2. 更换你的模板处理器。Jinja2(https://jinja.palletsprojects.com/)的语法几乎和Django模板语言一样,但它可以使用完整的Python功能,而且速度更快。你可以全面替换,或者只在你自己处理的模板中使用它,而对设计师维护的页面则继续使用Django的“更安全”的模板。

54

我只是添加了一个额外的模板标签,像这样:

@register.filter
def in_category(things, category):
    return things.filter(category=category)

然后我就可以这样做:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}
143

你不能这样做,这是有原因的。Django框架的设计者希望把展示代码和数据逻辑严格分开。过滤模型属于数据逻辑,而输出HTML属于展示逻辑。

所以你有几种选择。最简单的办法是先进行过滤,然后把结果传给 render_to_response。或者你可以在你的模型里写一个方法,这样你就可以用 {% for object in data.filtered_set %} 来表示。最后,你也可以自己写一个模板标签,不过在这个特定的情况下,我不建议这样做。

撰写回答