如何包含在运行时生成并存储在变量中的模板?

时间:2013-01-04 15:12:43

标签: python django django-templates django-views

商业:

所有设计web-app的实用背景,其中web-page由原型对象,小工具构建,每个小工具在其自己的view函数中单独定义(其自己的代码,不一定是django-view函数) )。为了构建“生产”网页,可以将它们放置在与此页面相关的常规视图中,并根据给定的源数据和其他参数生成网页元素。 例如,我有一个图表小工具,它接收源数据,参数,图表类型,美颜/颜色等,并绘制图表。如何将它存储在与特定ap,松耦合代码分开的存储中?哪种设计方法更好?

我尝试了什么:

我试过'哑'的方式:

例如,我有一个简单的观点:

from django.shortcuts import render_to_response
from django.template import Template, Context
from string import letters
def home(request):
    t = Template("""<ul>
                        {% for key, value in d.items %}
                            <li>{{ key }}: {{ value }}</li>
                        {% endfor %}
                    </ul>""")
    d = {k: v for v, k in enumerate(letters)}
    return render_to_response('home.html', {'t': t, 'd':d})

模板:

<html>
<head>
    <title>Django tests</title>

</head>
<body>
{% include t with d=d %}
</body>
</html>

通过这样的设置,我得到:TemplateDoesNotExist

对答案的期望:

我正在搜索任何合理的方案来存储网页块,这些网页设计为与自己的生活有关,与网页的其他元素分开或多或少,在网页中的类似单独的代码块中 - 应用程序后端。 例如,我可以提供以下项目:

谢谢!




PS

来自django-docs的摘录:

  

{%extends variable%}使用变量的值。如果变量   计算结果为字符串,Django将使用该字符串作为名称   父模板。 如果变量求值为Template对象,   Django将使用该对象作为父模板。

所以这意味着,使用{%extends%}标签,操作我所说的话肯定是可能的。

  

此示例包含名称为的模板的内容   包含在变量template_name中:

     

{% include template_name %}

所以这可能意味着,传递给{% include %}的变量只能是一个名为file的字符串。如果它是真的,那么我的问题很清楚 - 变量中定义的模板不能包含在常规模板中。
它对我来说仍然有些含糊不清,因为在Python中,name字可能被用作variable的同义词。

4 个答案:

答案 0 :(得分:3)

正如评论中已经提到的那样,您需要将模板渲染为字符串并将其传递给第二个模板,将其标记为安全字符串,以便不会自动转义。所以,你的例子是:

from django.shortcuts import render_to_response
from django.template import Template, Context
from django.utils.safestring import mark_safe
from string import letters
def home(request):
    t = Template("""<ul>
                        {% for key, value in d.items %}
                            <li>{{ key }}: {{ value }}</li>
                        {% endfor %}
                    </ul>""")
    c = Context({'d': {k: v for v, k in enumerate(letters)}})
    return render_to_response('home.html', {'t': mark_safe(t.render(c))})

然后,在home.html中,使用{{ t }}

进行渲染

答案 1 :(得分:1)

您应该将包含模板放在自己的文件中

include.html:

<ul>
    {% for key, value in d.items %}
        <li>{{ key }}: {{ value }}</li>
    {% endfor %}
</ul>

home.html的:

<html>
    <head>
        <title>Django tests</title>
    </head>
    <body>
        {% include 'include.html' with d=d %}
    </body>
</html>

然后您的观点变为:

def home(request):
    d = {k: v for v, k in enumerate(letters)}
    return render_to_response('home.html', {'d':d})

答案 2 :(得分:1)

您应该渲染子模板,然后将其放在home.html模板的上下文中(在这种情况下为t)。这就是我之前用于递归模板的内容。

home.html的

<html>
<head>
    <title>Django tests</title>
</head>
<body>
    {{ t }}
</body>
</html>

views.py

from django.shortcuts import render_to_response
from django.template import Template, Context
from string import letters

def home(request):
    t = Template("""<ul>
                        {% for key, value in d.items %}
                            <li>{{ key }}: {{ value }}</li>
                        {% endfor %}
                    </ul>""")
    d = {k: v for v, k in enumerate(letters)}
    t_rendered = t.render(Context({'d': d}))
    return render_to_response('home.html',
                              {'t': t_rendered})

请注意,您可以通过在视图外部创建子模板来缓存子模板,这样就不会在每个请求上创建子模板。您可以使用loader将子模板保存在模板文件中。但是,在重新启动服务器之前,更改不会反映出来。

from django.shortcuts import render_to_response
from django.template import Template, Context, loader
from string import letters

t = loader.get_template('subtemplate.html')

def home(request):
    d = {k: v for v, k in enumerate(letters)}
    t_rendered = t.render(Context({'d': d}))
    return render_to_response('home.html',
                              {'t': t_rendered})    

答案 3 :(得分:0)

我相信render_to_response是一种快捷操作。我认为它不需要模板作为第二个参数而是上下文

return render_to_response('home.html', {'d': d,})

<html>
<head>
    <title>Django tests</title>

</head>
<body>

<ul>
   {% for key, value in d.items %}
     <li>{{ key }}: {{ value }}
   {% endfor %}
</ul>

</body>
</html>

您可以在模板目录中创建一个列表模板,并将其包含在模板中 https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#include 看起来像包含模板名称而不是动态模板