【问题标题】:How to include template generated in runtime and stored in variable?如何包含在运行时生成并存储在变量中的模板?
【发布时间】:2013-01-04 15:12:43
【问题描述】:

业务:

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

我尝试了什么:

我尝试过“愚蠢”的方式:

例如我有一个简单的视图:

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

对答案的期望:

我正在寻找任何合理的方案来存储网页块,它的设计有点像自己的生活,与网页的其他元素或多或少地分开,在 web 中类似独立的代码块中-应用程序后端。 例如,我可以提供以下项目:

谢谢!




ps

django-docs 的摘录:

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

也就是说,使用 {% extends %} 标签,我所说的操作绝对是可能的。

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

{% include template_name %}

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

【问题讨论】:

    标签: python django django-templates django-views


    【解决方案1】:

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

    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 }} 进行渲染

    【讨论】:

      【解决方案2】:

      你应该把你的包含模板放在它自己的文件中

      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})
      

      【讨论】:

      【解决方案3】:

      您应该渲染您的子模板,然后将其放在您的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})    
      

      【讨论】:

        【解决方案4】:

        我相信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 看起来 include 只需要一个模板名称而不是一个动态模板

        【讨论】:

          猜你喜欢
          • 2017-01-08
          • 2015-12-28
          • 1970-01-01
          • 2017-10-11
          • 1970-01-01
          • 2014-05-14
          • 2015-06-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多