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

时间:2008-10-21 23:55:57

标签: python django django-templates

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

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

在我的模板中,我想做

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

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

6 个答案:

答案 0 :(得分:109)

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

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

答案 1 :(得分:28)

我只需添加一个额外的模板标签:

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

答案 2 :(得分:11)

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

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

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

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

答案 3 :(得分:8)

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

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)

答案 4 :(得分:7)

另一个选项是,如果你有一个总是想要应用的过滤器,那么在有问题的模型上添加custom manager,它总是将过滤器应用于返回的结果。

一个很好的例子是Event模型,对于你在模型上做的90%的查询,你会想要Event.objects.filter(date__gte=now)之类的东西,即你通常对{即将到来的{1}}。这看起来像是:

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() 模型上完成的所有默认查询应用了相同的过滤器,因此不像上面介绍的某些技术那样灵活。

答案 5 :(得分:1)

适用于在2020年寻找答案的任何人。 这对我有用。

视图中

 class InstancesView(generic.ListView):
        model = AlarmInstance
        context_object_name = 'settings_context'
        queryset = Group.objects.all()
        template_name = 'insta_list.html'

        @register.filter
        def filter_unknown(self, aVal):
            result = aVal.filter(is_known=False)
            return result

        @register.filter
        def filter_known(self, aVal):
            result = aVal.filter(is_known=True)
            return result

在模板中:

{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}

使用伪代码:

For each in model.child_object|view_filter:filter_arg

希望有帮助。