2016-06-15 9 views
5

私はdjangoテンプレート内でカスタムinclusion tagsを使い始めました。しかしDjangoテンプレートと空白

<a href='{% url ... %}'><img src='{{ ... }}' alt='...'> {{ profile.name }}</a> 

、私はそれを使用します。たとえば、私のようなので、プロフィールの画像の小さなバージョンと一緒にユーザープロファイルへのリンクを挿入し{% profilelink profile %}タグ(profilelink.html)を持っていますスニペット(sometemplate.html)以下:

<p>Owned by {% profilelink owner %} (uploaded by {% profilelink uploader %})</p> 

それから私は、2番目のテンプレートタグと閉じ括弧によって生成HTML間の空白を取得します。この空白は不要です。これは、ファイルprofilelink.htmlの最後の改行文字に由来します。これは非常に一般的な問題であり、Stackoverflowを検索すると、一般的なテンプレートの空白に関する多くの疑問が生じます。これまでに見つかった解決策の概要と、なぜ機能しないのですか。

これらの問題のいくつかは、{% spaceless %}タグで解決できますが、すべてではありません。このタグは、上記の例では当てはまりませんが、タグ間の空白のみを削除します。

可能な解決策の1つは、最終的なEOLがprofilelink.htmlにないことですが、それは非常に望ましくありません。理由:それは一般的に悪いスタイルです。いくつかのエディタ(vim)は、デフォルトで1つを静かに追加します。それは方法だPOSIX defines a line;一部のSCMが不幸になることがあります。

もう1つの解決策は、Jinja2のような別のテンプレートエンジンに切り替えることです。これはこの問題を解決することも解決しないこともあります。それは{% ... -%}のような構造をサポートしており、次のEOL文字を食べる。これはいくつかの状況では便利ですが、上記の例では役に立たないこともあります。しかし、このような小さな煩わしさのためにテンプレートのバックエンドを切り替えることは少し残酷すぎるように見え、別の依存関係を追加します。私は、標準的な "django"のやり方で何にでも固執したいと思います。しかし、Jinja2を新しいDjangoのデフォルトにする予定は明らかです。

ミドルウェアクラスを使用して、生成されたHTMLから余分な空白を削除してから、ブラウザに送信することを提案している人がいました。これは便利ですが、機能的に同等の方法でHTMLを変換する場合にのみ有効です。つまり、同じセマンティクスがブラウザに表示されます。それは私が望むものではないので、セマンティクスが実際に変化して適切に表示されるようにしたい。これは一般的なミドルウェアクラスで実装することは不可能です。私はテンプレート自体の中からケースバイケースでこれをコントロールする必要があります。私はHTMLをもっときれいにすることに気をつけません。最初は正しいことが気になります。

も引数(引用)とWONTFIXとしてクローズされたbug #2594あります「Djangoテンプレート言語は空白に敏感ではないHTMLを生成するための十分です」。私の指導では、これはまったく間違っています。 HTMLは空白に非常に敏感ですが、それがどれだけあるか気にしません。空白があるのか​​全く空いているのかが大事です。

私の質問には次のようなものがあります:この問題を一般的に解決するための純粋な方法はありますか? (一部の状況だけではなく、常に動作するもの)

(CSSベースの修正はカウントされません。)

+2

最も洗練された解決策ではありませんが、 '@ register'デコレータの代わりに' get_template'を使うことを考えて、タグを登録する前にテンプレート文字列から改行を取り除くことができます。もう1つ考えて、これをデコレータにすることもできます。 – Selcuk

+0

@Selcuk私はこれをやろうとしましたが成功しませんでした。少なくとも私が避けたいと思うテンプレートシステムの内部に突っ込むことはありません。あなたや他の誰かが実用的なソリューションを投稿することができれば、それは素晴らしいことです。 – jlh

答えて

2

:その後、

from django import template 
from django.template.defaultfilters import stringfilter 

register = template.Library() 

@register.filter 
@stringfilter 
def trim(value): 
    return value.strip() 

そして、次のようにそれを使用しますインクルージョンタグの代わりにsimple_tagを使用することが望ましいでしょう。

私はあなたのタグは、このようなものであると仮定します。

@register.inclusion_tag('profilelink.html') 
def profilelink(user): 
    return {"profile": user} 

from django.template.loader import render_to_string 

@register.simple_tag 
def profilelink(user): 
    t = render_to_string("profilelink.html", {"profile": user}) 
    return t.strip() 

でこれを代用することも可能であろう、私は今、私の前にDjangoのプロジェクトを持っていません、これはテストされていません。

1

これまで私が考え出した最高のものです。私はまだもっと良い解決策を望んでいますが、今のところそれができます。

私はベース/ templatetags/basetags.yptaken from this answer)で、このようなカスタムフィルタを定義した:私は1つのソリューションを信じる

{% load basetags %} 
<p>Owned by {% profilelink owner %} (uploaded by 
{% filter trim %}{% profilelink uploader %}{% endfilter %})</p> 
関連する問題