92

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

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

在我的模板中我想做

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

但我似乎不知道如何编写过滤器。

4

6 回答 6

131

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

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

于 2008-10-22T00:00:27.900 回答
48

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

@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 %}
于 2013-05-07T21:41:18.687 回答
13

我经常遇到这个问题,并且经常使用“添加方法”解决方案。但是,肯定存在“添加方法”或“在视图中计算”不起作用(或效果不佳)的情况。例如,当您缓存模板片段并需要一些重要的数据库计算来生成它时。除非您需要,否则您不想做 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 的“更安全”模板。

于 2008-10-23T17:22:35.767 回答
11

另一种选择是,如果您有一个始终想要应用的过滤器,请在相关模型上添加一个自定义管理器,该管理器始终将过滤器应用于返回的结果。

一个很好的例子是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()

但同样,这对Event模型上完成的所有默认查询应用相同的过滤器,因此上述一些技术并不灵活。

于 2012-09-10T11:37:01.857 回答
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)

编辑: assignment_tag 在 Django 2.0 中被删除,这将不再有效。

于 2012-12-23T12:27:28.033 回答
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

希望有帮助。

于 2020-04-30T09:13:01.020 回答