我需要从Django模板中执行过滤查询,以在视图中获取与python代码等效的一组对象:
queryset = Modelclass.objects.filter(somekey=foo)
在我的模板中,我想做
{% for object in data.somekey_set.FILTER %}
但我似乎无法找出如何编写FILTER。
Answers:
您不能这样做,这是设计使然。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 %}
'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d
。有任何想法吗?
我经常遇到此问题,并经常使用“添加方法”解决方案。但是,肯定存在“添加方法”或“在视图中计算”的情况不起作用(或效果不佳)的情况。例如,当您缓存模板片段并且需要一些不平凡的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)
对于任何在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
希望能有所帮助。