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

我需要从一个Django模板中执行一个过滤的查询,以获得一组等同于视图内的python代码的对象:

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

在我的模板中,我想要做的

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

但我似乎无法find如何写FILTER。

你不能这样做,这是devise。 Django框架作者希望将表示代码与数据逻辑严格区分开来。 过滤模型是数据逻辑,输出HTML是表示逻辑。

所以你有几个select。 最简单的做法是过滤,然后将结果传递给render_to_response 。 或者你可以在你的模型中写一个方法,这样你就可以{% for object in data.filtered_set %} 。 最后,你可以写自己的模板标签,虽然在这个特定的情况下,我会build议反对的。

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

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

我经常遇到这个问题,经常使用“添加方法”的解决scheme。 但是,肯定有“添加方法”或“在视图中计算”的情况,不起作用(或者效果不好)。 例如,当你caching模板片段,并需要一些不平凡的数据库计算来产生它。 除非需要,否则不需要进行数据库工作,但是直到深入了解模板逻辑之后,才会知道是否需要。

其他可能的解决scheme:

  1. 使用http://www.djangosnippets.org/snippets/9/中的;{%expr <expression>作为<var_name>%}模板标签。expression式是模板的Context作为本地作用域的合法Pythonexpression式。

  2. 改变你的模板处理器。 Jinja2( http://jinja.pocoo.org/2/ )的语法与Django模板语言几乎完全相同,但具有完整的Pythonfunction。 它也更快。 您可以批量执行此操作,也可以将其用于正在处理的模板,但是对于devise器维护的页面使用Django的“更安全”模板。

这可以通过赋值标签来解决:

 from django import template register = template.Library() @register.assignment_tag def query(qs, **kwargs): """ template tag which allows queryset filtering. Usage: {% query books author=author as mybooks %} {% for book in mybooks %} ... {% endfor %} """ return qs.filter(**kwargs) 

另一个select是,如果您有一个您始终需要应用的filter,请在所讨论的模型上添加一个自定义pipe理器 ,该模型始终将filter应用于返回的结果。

一个很好的例子就是一个Event模型,在这个模型中,有90%的查询需要类似Event.objects.filter(date__gte=now) ,也就是说,你通常对Events感兴趣即将到来的。 这看起来像:

 class EventManager(models.Manager): def get_query_set(self): now = datetime.now() return super(EventManager,self).get_query_set().filter(date__gte=now) 

而在模型中:

 class Event(models.Model): ... objects = EventManager() 

但是同样,这个filter对所有在Event模型上完成的默认查询都应用了相同的filter,所以不像上面描述的那样灵活。