我需要从 django 模板中执行过滤查询,以在视图中获取一组等效于 python 代码的对象:
queryset = Modelclass.objects.filter(somekey=foo)
在我的模板中我想做
{% for object in data.somekey_set.FILTER %}
但我似乎不知道如何编写过滤器。
我需要从 django 模板中执行过滤查询,以在视图中获取一组等效于 python 代码的对象:
queryset = Modelclass.objects.filter(somekey=foo)
在我的模板中我想做
{% for object in data.somekey_set.FILTER %}
但我似乎不知道如何编写过滤器。
你不能这样做,这是设计使然。Django 框架的作者打算将表示代码与数据逻辑严格分离。过滤模型是数据逻辑,输出 HTML 是表示逻辑。
所以你有几个选择。最简单的方法是进行过滤,然后将结果传递给render_to_response
. 或者你可以在你的模型中写一个方法,这样你就可以说{% for object in data.filtered_set %}
. 最后,您可以编写自己的模板标签,尽管在这种特定情况下我建议不要这样做。
我只是添加了一个额外的模板标签,如下所示:
@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 %}
我经常遇到这个问题,并且经常使用“添加方法”解决方案。但是,肯定存在“添加方法”或“在视图中计算”不起作用(或效果不佳)的情况。例如,当您缓存模板片段并需要一些重要的数据库计算来生成它时。除非您需要,否则您不想做 DB 工作,但在深入了解模板逻辑之前,您不会知道是否需要。
其他一些可能的解决方案:
使用http://www.djangosnippets.org/snippets/9/上的 {% expr <expression> as <var_name> %} 模板标签。表达式是任何合法的 Python 表达式,模板的 Context 作为本地范围。
更改您的模板处理器。Jinja2 ( http://jinja.pocoo.org/2/ ) 的语法几乎与 Django 模板语言相同,但具有完整的 Python 功能。它也更快。您可以批量执行此操作,或者您可以将其使用限制为您正在处理的模板,但对设计师维护的页面使用 Django 的“更安全”模板。
另一种选择是,如果您有一个始终想要应用的过滤器,请在相关模型上添加一个自定义管理器,该管理器始终将过滤器应用于返回的结果。
一个很好的例子是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
模型上完成的所有默认查询应用相同的过滤器,因此上述一些技术并不灵活。
这可以通过赋值标签来解决:
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 中被删除,这将不再有效。
对于任何在 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
希望有帮助。