139

同じ django テンプレートで同じ{% block %}を 2 回使用したいと考えています。このブロックをベース テンプレートに複数回表示したい:

# base.html
<html>
    <head>
        <title>{% block title %}My Cool Website{% endblock %}</title>
    </head>
    <body>
        <h1>{% block title %}My Cool Website{% endblock %}</h1>
    </body>
</html>

そしてそれを拡張します:

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}

# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}

Django がブロックを 1 回だけ表示することを望んでいるため、例外が発生します。

/ での TemplateSyntaxError

「タイトル」という名前の「ブロック」タグが複数回表示されます

手っ取り早い解決策は、ブロックタイトルtitle1title2に複製することです。

# blog.html
{% extends 'base.html' %}
{% block title1 %}My Blog{% endblock %}
{% block title2 %}My Blog{% endblock %}

しかし、これはDRYの原則に違反しています。継承するテンプレートがたくさんあり、地獄に行きたくないので、非常に難しいでしょう;-)

この問題に対するトリックまたは回避策はありますか? すべてのコードを複製せずに、テンプレートで同じブロックを繰り返すにはどうすればよいですか?

4

14 に答える 14

82

Django テンプレート マクロ プラグインを使用します。

https://gist.github.com/1715202 (ジャンゴ >= 1.4)

また

http://www.djangosnippets.org/snippets/363/ (ジャンゴ < 1.4)

ジャンゴ >= 1.4

# base.html
{% kwacro title %}
    {% block title %}My Cool Website{% endblock %}
{% endkwacro %}

<html>
    <head>
        <title>{% usekwacro title %}</title>
    </head>
    <body>
        <h1>{% usekwacro title %}</h1>
    </body>
</html>

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

ジャンゴ < 1.4

# base.html
{% macro title %}
    {% block title %}My Cool Website{% endblock %}
{% endmacro %}

<html>
    <head>
        <title>{% usemacro title %}</title>
    </head>
    <body>
        <h1>{% usemacro title %}</h1>
    </body>
</html>

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
于 2009-09-22T19:09:07.590 に答える
20

おそらく、実際にはブロックを使用するのではなく、単に変数を使用したいでしょう:

# base.html
<html>
    <head>
        <title>{{ title|default:"My Cool Website" }}</title>
    </head>
    <body>
        <h1>{{ title|default:"My Cool Website" }}</h1>
    </body>
</html>

次に、コンテキストを通じてタイトルを設定します。

于 2009-02-04T12:19:08.823 に答える
16

自分で同じことをしようとしたときに発見した方法は次のとおりです。

# base_helper.html
<html>
    <head>
        <title>{% block _title1 %}{% endblock %}</title>
    </head>
    <body>
        <h1>{% block _title2 %}{% endblock %}</h1>
    </body>
</html>


# base.html
{% extends "base_helper.html" %}

# Copy title into _title1 & _title2, using "My Cool Website" as a default.
{% block _title1 %}{% block _title2 %}{% block title %}My Cool Website{% endblock %}{% endblock %}{% endblock %}

残念ながら追加のファイルが必要ですが、ビューからタイトルを渡す必要はありません。

于 2009-09-27T14:39:41.623 に答える
12

{% include subtemplate.html %}複数回使用できます。ブロックと同じではありませんが、うまくいきます。

于 2009-02-04T12:31:44.243 に答える
6

ここでいくつかの議論があります: http://code.djangoproject.com/ticket/4529 明らかに、django コア チームは、これは一般的に使用されるシナリオではないと考えているため、このチケットを拒否しますが、私は同意しません。

繰り返しブロックは、このためのシンプルでクリーンな実装です: https://github.com/SmileyChris/django-repeatblock

テンプレート マクロは別のものですが、慎重にテストされていないと著者は述べています: http://www.djangosnippets.org/snippets/363/

リピートブロックを使用しました。

于 2011-01-23T05:47:20.063 に答える
5

do_set上記とdo_getテンプレートタグの回答に似た軽量のソリューションを次に示します。Django では、グローバル変数を定義できるタグにテンプレート コンテキスト全体を渡すことができます。

base.html:

<!DOCTYPE html>
<html lang="en">
<head>
  {% block head %}
    <title>{{ title }}</title>
  {% endblock %}
</head>
<body>
  <h1>{{ title }}</h1>
</body>
</html>

page.html:

{% extends "base.html" %}

{% block head %}
  {% define 'title' 'Homepage | title' %}
  {{ block.super }}
{% endblock %}

カスタムタグ (ここでアイデアを得ました: https://stackoverflow.com/a/33564990/2747924 ):

@register.simple_tag(takes_context=True)
def define(context, key, value):
    context.dicts[0][key] = value
    return ''

{% load %}また、カスタム タグを忘れずに、テンプレート オプションのビルトインリストに追加して、すべてのテンプレートに読み込む必要がないようにしてください。このアプローチの唯一の制限は{% define %}、ブロック タグ内から呼び出す必要があることです。これは、子テンプレートは親タグに一致するブロック タグのみをレンダリングするためです。それを回避する方法があるかどうかはわかりません。また、define明らかにそれを使用しようとする前に、呼び出しが来ることを確認してください。

于 2017-01-10T22:34:22.533 に答える
3

私も、テンプレート ファイルで {% block %} を繰り返す同じ必要性に遭遇しました。問題は、Django {% block %} を Django 条件のいずれの場合にも使用することと、現在のファイルを拡張する可能性のある後続のファイルによって {% block %} を上書き可能にすることです。(したがって、この場合、私が望むのは、技術的に再利用していないため、変数よりもブロックの方が確実であり、条件の両端に表示されるだけです。

問題:

次のDjangoテンプレートコードはテンプレート構文エラーになりますが、定義された{%ブロック%}を条件で再利用することは有効な「欲求」だと思います(つまり、Djangoパーサーが両方の端で構文を検証するのはなぜですか?条件式の場合、TRUTHY 条件のみを検証するべきではありませんか?)

# This example shows a {{ DEBUG }} conditional that loads 
#   Uncompressed JavaScript files if TRUE 
#   and loads Asynchronous minified JavaScript files if FALSE.  

# BASE.html
{% if DEBUG %}
    <script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
    <script type="text/javascript">
        {% block page_js %}
            var page = new $site.Page();
        {% endblock page_js %}
    </script>
{% else %}
    <script type="text/javascript">
        // load in the PRODUCTION VERSION of the site
        // minified and asynchronosly loaded
        yepnope([
            {
                load : '{MEDIA_URL}}js/flatfiles.min.js',
                wait : true,
                complete : function() {
                    {% block page_js %} // NOTE THE PAGE_JS BLOCK
                        var page = new $site.Page();
                    {% endblock page_js %}
                }
            }
        )];
    </script>
{% endif %}

# ABOUT.html
{% extends 'pages/base.html' %}
{% block page_js %}
var page = new $site.Page.About();
{% endblock page_js %}

ソリューション:

{% include %} を使用して、条件付きで {% block %} を複数回挿入できます。Django構文チェッカーにはTRUTHY {% include %}のみが含まれているため、これはうまくいきました。以下の結果を参照してください。

# partials/page.js
{% block page_js %}
    var page = new $site.Page();    
{% endblock %}

# base.html
{% if DEBUG %}
    <script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
    <script type="text/javascript">
        {% include 'partials/page_js.html' %}
    </script>
{% else %}
    <script type="text/javascript">
        yepnope([
            {
                load : '{MEDIA_URL}}js/flatfiles.min.js',
                wait : true,
                complete : function() {
                    {% include 'partials/page_js.html' %}
                }
            }
        )];
    </script>
{% endif %}
于 2011-03-23T18:48:04.487 に答える
3

Van Gale の提案に基づいて、以下を templatetags.py ファイルに追加することで、get タグと set タグを作成できます。

register = template.Library()

Stateful = {}
def do_set(parser, token):
    _, key = token.split_contents()
    nodelist = parser.parse(('endset',))
    parser.delete_first_token()  # from the example -- why?
    return SetStatefulNode(key,nodelist)

class SetStatefulNode(template.Node):
    def __init__(self, key, nodes):
        Stateful[key] = nodes
    def render(self, context):
        return ''
register.tag('set', do_set)

def do_get(parser, token):
    tag_name, key = token.split_contents()
    return GetStatefulNode(key)

class GetStatefulNode(template.Node):
    def __init__(self, key):
       self.key = key
    def render(self, context):
        return ''.join( [x.render(context) for x in Stateful[self.key]] )

register.tag('get', do_get)

次に、あるテンプレートで値を設定し、別のテンプレートで値{% set foo %}put data here{% endset %}を取得します{% get foo %}

于 2010-01-08T18:34:17.493 に答える
1

これには 2 つの簡単な解決策があります。

最も簡単なのは、タイトルをコンテキスト変数に入れることです。ビューでコンテキスト変数を設定します。

ジェネリック ビューのようなものを使用していて、写真や猫などの views.py がない場合は、 context に変数を設定するカスタム テンプレート タグを使用できます。

このルートに行くと、次のようなことができるようになります。

{% extends "base.html" %}
{% load set_page_title %}
{% page_title "My Pictures" %}
...

次に、base.html で:

...
{% block title %}{{ page_title }}{% endblock %}
...
<h1>{{ page_title }}</h1>
于 2009-02-04T12:20:05.703 に答える
-3

小枝では、次のように作成できます。

# base.html
<html>
    <head>
        <title>{{ block('title') }}</title>
    </head>
    <body>
        <h1>{{ block('title') }}</h1>
    </body>
</html>

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}

# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}
于 2011-09-01T06:22:28.267 に答える