web-dev-qa-db-ja.com

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の両方の形式で同じページを提供することであり、形式はわずかに異なります。ただし、上記の質問は、問題を解決できるという答えが得られれば、私がやろうとしていることを単純化します。

98
Net Citizen

Extendsテンプレートタグを使用すると、現在のテンプレートが別のテンプレートを拡張していること、つまり、親テンプレートに依存する子テンプレートであるということになります。 Djangoは、子テンプレートを見て、そのコンテンツを使用して親テンプレートを作成します。

子テンプレートで使用するすべてのものは、Djangoが親の設定に使用するブロック内にある必要があります。その子テンプレートでincludeステートメントを使用する場合は、Djangoが意味をなすように、ブロック内に含める必要があります。さもなければ、それは意味をなさず、Djangoはそれをどうするかを知りません。

Djangoのドキュメントには、親テンプレート内のブロックを置き換えるためにブロックを使用するいくつかの本当に良い例があります。

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

101
Matt Howell

Djangoドキュメントから:

Includeタグは、「このサブテンプレートを解析して、親の一部であるかのようにそのコンテンツを含める」のではなく、「このサブテンプレートをレンダリングしてHTMLを含める」の実装と見なす必要があります。これは、含まれるテンプレート間で共有状態がないことを意味します。各インクルードは完全に独立したレンダリングプロセスです。

そのため、Djangoはcommondata.htmlからブロックを取得せず、ブロック外でレンダリングされたhtmlをどうするかを知りません。

74
podshumok

これはあなたのためのトリックを行う必要があります:ブロックセクションの内側にインクルードタグを置きます。

page1.html:

{% extends "base1.html" %}

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

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}
17
Pavel Černý

将来の人々を助けるために、なぜそれが私のために機能しなかったのかについての詳細情報:

動作しなかった理由は、Djangoの{%include%}が派手なアポストロフィのような特殊文字を好まないためです。含めようとしていたテンプレートデータは、Wordから貼り付けられました。これらの特殊文字をすべて手動で削除する必要があり、その後正常に含まれました。

12
Net Citizen

含まれているファイルから子テンプレートにブロックをプルして、親テンプレートのブロックをオーバーライドすることはできません。ただし、変数に親を指定し、コンテキストでベーステンプレートを指定することができます。

ドキュメント から:

{%extends variable%}は、変数の値を使用します。変数が文字列に評価される場合、Djangoはその文字列を親テンプレートの名前として使用します。変数がTemplateオブジェクトに評価される場合、Djangoはそのオブジェクトを親テンプレートとして使用します。

個別の「page1.html」と「page2.html」の代わりに、「commondata.html」の先頭に{% extends base_template %}を配置します。次に、ビューでbase_templateを「base1.html」または「base2.html」のいずれかに定義します。

3
emery

グーグル経由でこれを見つける将来の人々への参照のために追加:このような場合のためにメザニンライブラリによって提供される{%overextend%}タグを見たいかもしれません。

2
Ted

2015年12月10日編集:コメントで指摘されているように、ssiはバージョン1.8から非推奨になりました。ドキュメントによると:

このタグは廃止され、Django 1.10で削除されます。代わりにincludeタグを使用してください。


私の意見では、この質問に対する正しい(最良の)答えは、podshumokからのものです。

ただし、ssiタグについて特に言及されていないことに驚かされました(=Djangoテンプレートシステムは、inlinetextの外部部分を含む。ここで、inlineは、外部テキストが解釈、解析、または補間されず、呼び出しテンプレート内で単に「コピー」されることを意味します。

詳細については、ドキュメントを参照してください(ページの右下にあるセレクターで適切なバージョンの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定義にも注意してください。

1