django模板:包括和扩展

问题:django模板:包括和扩展

我想在2个不同的基本文件中提供相同的内容。

所以我正在尝试这样做:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

page2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

问题是我似乎无法同时使用扩展和包含。有什么办法吗?如果没有,我该如何完成以上工作?

commondata.html覆盖base1.html和base2.html中指定的块

这样做的目的是提供pdf和html格式的同一页面,但格式略有不同。上面的问题虽然简化了我要尝试做的事情,但是如果我可以得到答案,它将解决我的问题。

I would like to provide the same content inside 2 different base files.

So I’m trying to do this:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

page2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

The problem is that I can’t seem to use both extends and include. Is there some way to do that? And if not, how can I accomplish the above?

commondata.html overrides a block that is specified in both base1.html and base2.html

The purpose of this is to provide the same page in both pdf and html format, where the formatting is slightly different. The above question though simplifies what I’m trying to do so if I can get an answer to that it will solve my problem.


回答 0

使用扩展模板标签时,是指当前模板扩展了另一个模板-它是子模板,取决于父模板。Django将查看您的子模板,并使用其内容填充父模板。

您想要在子模板中使用的所有内容都应位于block之内,Django使用该块来填充父模板。如果要在该子模板中使用include语句,则必须将其放在一个块中,以便Django理解。否则,这只是没有意义,而Django不知道该怎么做。

Django文档中有一些非常好的示例,这些示例使用块替换父模板中的块。

https://docs.djangoproject.com/zh-CN/dev/ref/templates/language/#template-inheritance

When you use the extends template tag, you’re saying that the current template extends another — that it is a child template, dependent on a parent template. Django will look at your child template and use its content to populate the parent.

Everything that you want to use in a child template should be within blocks, which Django uses to populate the parent. If you want use an include statement in that child template, you have to put it within a block, for Django to make sense of it. Otherwise it just doesn’t make sense and Django doesn’t know what to do with it.

The Django documentation has a few really good examples of using blocks to replace blocks in the parent template.

https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance


回答 1

从Django文档中:

include标记应被视为“呈现此子模板并包含HTML”的实现,而不应视为“解析此子模板并像其父对象一样包含其内容”。这意味着在包含的模板之间没有共享状态-每个包含都是一个完全独立的呈现过程。

因此,Django不会从您的commondata.html中获取任何块,并且它也不知道如何处理呈现的html外部块。

From Django docs:

The include tag should be considered as an implementation of “render this subtemplate and include the HTML”, not as “parse this subtemplate and include its contents as if it were part of the parent”. This means that there is no shared state between included templates — each include is a completely independent rendering process.

So Django doesn’t grab any blocks from your commondata.html and it doesn’t know what to do with rendered html outside blocks.


回答 2

这应该为您解决了问题:将include标签放在块部分中。

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}

This should do the trick for you: put include tag inside of a block section.

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}

回答 3

如果它对将来的人有帮助,为什么它对我不起作用的更多信息:

之所以不起作用,是因为django中的{%include%}不喜欢像特殊的撇号这样的特殊字符。我尝试包含的模板数据是从Word粘贴的。我必须手动删除所有这些特殊字符,然后成功包含其中。

More info about why it wasn’t working for me in case it helps future people:

The reason why it wasn’t working is that {% include %} in django doesn’t like special characters like fancy apostrophe. The template data I was trying to include was pasted from word. I had to manually remove all of these special characters and then it included successfully.


回答 4

您不能将包含文件中的块拉入子模板以覆盖父模板的块。但是,您可以在变量中指定父项,并在上下文中指定基本模板。

文档中

{%扩展变量%}使用变量的值。如果该变量的值为字符串,则Django将使用该字符串作为父模板的名称。如果该变量的值为模板对象,则Django将使用该对象作为父模板。

代替单独的“ page1.html”和“ page2.html”,放在“ commondata.html” {% extends base_template %}的顶部。然后在您的视图中,定义base_template为“ base1.html”或“ base2.html”。

You can’t pull in blocks from an included file into a child template to override the parent template’s blocks. However, you can specify a parent in a variable and have the base template specified in the context.

From the documentation:

{% extends variable %} uses the value of variable. If the variable evaluates to a string, Django will use that string as the name of the parent template. If the variable evaluates to a Template object, Django will use that object as the parent template.

Instead of separate “page1.html” and “page2.html”, put {% extends base_template %} at the top of “commondata.html”. And then in your view, define base_template to be either “base1.html” or “base2.html”.


回答 5

添加以供将来通过Google找到它的人参考:对于此类情况,您可能需要查看夹层库提供的{%overextend%}标签。

Added for reference to future people who find this via google: You might want to look at the {% overextend %} tag provided by the mezzanine library for cases like this.


回答 6

编辑2015年12月10日:正如评论中指出的那样,自1.8版起不推荐使用ssi。根据文档:

该标签已被弃用,并将在Django 1.10中删除。请改用include标签。


在我看来,这个问题的正确答案(最好)是podshumok提出的答案,因为它解释了为什么在与继承一起使用时include的行为。

但是,令我感到有些惊讶的是,没有人提到Django模板系统提供的ssi标记,该标记是专门为内联式设计的,包括一个外部文本。在此,内联表示不会解释,解析或插入外部文本,而只是在调用模板内部“复制”。

请参考文档以获取更多详细信息(请确保在页面右下方的选择器中检查您所使用的Django版本)。

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

从文档中:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
 which must be specified using an absolute path  in the current page

还请注意此技术的安全隐患以及必需的ALLOWED_INCLUDE_ROOTS定义,必须将其添加到设置文件中。

Edit 10th Dec 2015: As pointed out in the comments, ssi is deprecated since version 1.8. According to the documentation:

This tag has been deprecated and will be removed in Django 1.10. Use the include tag instead.


In my opinion, the right (best) answer to this question is the one from podshumok, as it explains why the behaviour of include when used along with inheritance.

However, I was somewhat surprised that nobody mentioned the ssi tag provided by the Django templating system, which is specifically designed for inline including an external piece of text. Here, inline means the external text will not be interpreted, parsed or interpolated, but simply “copied” inside the calling template.

Please, refer to the documentation for further details (be sure to check your appropriate version of Django in the selector at the lower right part of the page).

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

From the documentation:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
– which must be specified using an absolute path – in the current page

Beware also of the security implications of this technique and also of the required ALLOWED_INCLUDE_ROOTS define, which must be added to your settings files.