你可以制作一个返回查询集的自定义模板标签吗?如果是,如何? - 姜戈

Posted

技术标签:

【中文标题】你可以制作一个返回查询集的自定义模板标签吗?如果是,如何? - 姜戈【英文标题】:Can you make a custom template tag that returns a queryset? If yes, how? - Django 【发布时间】:2011-12-18 17:37:44 【问题描述】:

让我们为我的 SOians 同胞(?)变得非常容易。

这是自定义模板标签的正常工作方式 -

模板->

% block content %

     blah blah blah

     % custom_tag_load %

% endblock %

调用 custom_tag_load 并返回一个字符串。我想要返回的是一个查询集,我可以像这样使用它->

% block content %

     blah blah blah

     % for x in custom_tag_load %

           x.datetime 

     % endfor %

% endblock %

注意 -> 我基本上想要做的是避免通过视图传递查询集,我不确定我是否应该在我的全局上下文中轻松存储查询集。

【问题讨论】:

这有点违背了 MVC 的全部意义。这是一个有趣的问题,但一般来说,视图层永远不应该直接从数据库中获取数据。不过,如果有一个有趣的问题,请 +1。 @Chris,这真的不是真的。您不想从模板中的数据库中获取核心对象,但辅助内容(例如最近帖子的侧边栏)在模板标签中非常有意义。 【参考方案1】:

您可以从标签中返回任何您喜欢的内容,包括查询集。但是,您不能在 for 标签内使用标签 - 您只能在其中使用变量(或通过过滤器传递的变量)。您可以做的是让您的标签将查询集放入上下文中的变量中,并在 for 循环中使用该变量。请参阅 how to set a variable from a tag 上的文档 - 尽管请注意开发版本 has an easier method 用于执行此操作。

但是,您也不应该担心将查询集放入上下文处理器中。不要忘记查询集是惰性的,因此除非在模板中评估或迭代查询集,否则不会命中数据库。

【讨论】:

啊,有道理。为什么好东西总是在开发版?? FML 我有同样的问题,但答案并没有太大帮助。很难理解,链接失效了。 对于无法理解此答案的人,请查看 THIS 以创建上下文变量。【参考方案2】:

模板标签可以做任何你想做的事。从您的伪代码中,您可以使用包含标签完成您需要的工作:

#my_tags.py
from django import template
from my_app.models import MyModel

register = template.Library()

@register.inclusion_tag('my_template.html')
def my_custom_tag():
    things = MyModel.objects.all()
    return 'things' : things


#my_template.html
% if things %
    <ul>
    % for thing in things %
        <li> thing </li>    
    % empty %
        <li>Sorry, no things yet.</li>
    % endfor %
    </ul>
% endif %


#the_view.html
% load my_tags %

% my_custom_tag %

或者,您可以编写一个自定义标签,将查询集添加到上下文中。希望对您有所帮助。

【讨论】:

嘿布兰登,这正是我想要避免的那种事情,我不希望“my_template.html”在“the_view.html”之外。感谢您的回复。【参考方案3】:

我最近也遇到了同样的问题,这里的大多数答案都已经过时了,但是稍微挖掘了一下 Django 的文档,我就可以解决了。

像上面的大多数答案一样,您基本上可以使用模板标签返回任何内容,但这完全取决于您如何注册模板标签。所以说你想使用一个模板标签来返回一个查询集可用于你想要的任何模板,你可以像这样将模板标签注册为一个简单的标签

from django import template    
from blog.models import Post
from django.template.defaulttags import register

register = template.Library()

@register.simple_tag
def get_posts():
    return Post.objects.all()

然后为了能够在你的模板中访问这个,你首先需要在你的模板中加载这个文件,比如

% load templatetagfile %

然后要循环,需要先赋值给一个变量,然后再循环

% get_posts as posts %
% for post in posts %
     post.whatever 
% endfor %

那里的第一行使 get_posts 函数中的查询集可用作名为 posts 的变量,然后您可以循环访问该变量。

【讨论】:

以上是关于你可以制作一个返回查询集的自定义模板标签吗?如果是,如何? - 姜戈的主要内容,如果未能解决你的问题,请参考以下文章

我可以将我的自定义模板标签文件夹移到我的应用程序之外吗?

Django更改查询集字段不影响数据库

我可以在返回 html 的自定义 Tag Helper 中使用 Tag Helper 吗?

PHP的自定义模板引擎

在带有多个参数的自定义模板标签的模板中使用“if”

具有过滤查询集的组权限的自定义表单