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

Ber*_*Ber 74 python django django-templates

我需要在django模板中执行过滤查询,以获得一组与视图中的python代码等效的对象:

queryset = Modelclass.objects.filter(somekey=foo)
Run Code Online (Sandbox Code Playgroud)

在我的模板中,我想做

{% for object in data.somekey_set.FILTER %}
Run Code Online (Sandbox Code Playgroud)

但我似乎无法找到如何写FILTER.

Eli*_*ght 113

你不能这样做,这是设计的.Django框架作者希望严格分离表示代码和数据逻辑.过滤模型是数据逻辑,输出HTML是表示逻辑.

所以你有几个选择.最简单的方法是进行过滤,然后将结果传递给render_to_response.或者您可以在模型中编写一个方法,以便您可以说{% for object in data.filtered_set %}.最后,您可以编写自己的模板标记,但在这种特定情况下,我会建议不要这样做.

  • @andi除了您根据权限过滤内容的情况,这些权限永远不会在客户端完成.对? (7认同)
  • 你好人民现在是2014年!大约6年后,JS库取得了巨大的进步,并且应该在客户端完成对非常大量数据的过滤,并支持一些不错的java脚本库,或者至少是AJAX-ed. (2认同)
  • @andi:我当然同意即使是中等规模的数据集,例如表中的数千行。在处理数百万行的数据库后,仍然有一个地方可以进行服务器端过滤:) (2认同)

tob*_*ych 29

我只是添加一个额外的模板标签,如下所示:

@register.filter
def in_category(things, category):
    return things.filter(category=category)
Run Code Online (Sandbox Code Playgroud)

然后我可以这样做:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)


Pet*_*ell 11

我经常遇到这个问题,经常使用"添加方法"解决方案.但是,确实存在"添加方法"或"在视图中计算"不起作用(或不能正常工作)的情况.例如,当您缓存模板片段并需要一些非平凡的DB计算来生成它时.除非您需要,否则您不希望执行数据库工作,但在深入了解模板逻辑之前,您不会知道是否需要.

其他可能的解决方案:

  1. 使用http://www.djangosnippets.org/snippets/9/上的{%expr <expression> as <var_name>%}模板标记.表达式是任何合法的Python表达式,模板的Context作为本地范围.

  2. 更改模板处理器.Jinja2(http://jinja.pocoo.org/2/)的语法几乎与Django模板语言相同,但具有完整的Python功能.它也更快.您可以批量执行此操作,或者可以将其用途限制为正在使用的模板,但是将Django的"更安全"模板用于设计者维护的页面.


chr*_*isv 9

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

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)
Run Code Online (Sandbox Code Playgroud)

  • assignment_tag已在Django 2.0中删除 (3认同)

mrm*_*oey 8

另一个选项是,如果您有一个总是需要应用的过滤器,则在相关模型上添加自定义管理器,该管理器始终将过滤器应用于返回的结果.

一个很好的例子就是一个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)
Run Code Online (Sandbox Code Playgroud)

在模型中:

class Event(models.Model):
    ...
    objects = EventManager()
Run Code Online (Sandbox Code Playgroud)

但同样,这对于在Event模型上完成的所有默认查询应用相同的过滤器,因此不像上面描述的某些技术那样灵活.