2013-08-19 33 views
5

スタンドアロンアプリケーションのDjangoテンプレートシステムによって前処理された人間が読めるHTMLとCSSコード(適切にインデントされている)を生成したい。Djangoテンプレートの適切な字下げ(サルのパッチ適用なし)?

django.template.baseモジュールにあるNodeListクラスからrenderメソッドを変更しました。私のコードは正常に動作しているようですが、私は古いレンダリングメソッドを置き換えるためにサルパッチを使用しています。

この場合、サルパッチを使用しないより洗練された方法がありますか?あるいは、ここでは猿のパッチが最善の方法でしょうか?

私のコードは次のようになります。

''' 
This module monkey-patches Django template system to preserve 
indentation when rendering templates. 
''' 

import re 

from django.utils.encoding import force_text 
from django.utils.safestring import mark_safe 
from django.template.loader import render_to_string 
from django.template import Node, NodeList, TextNode 
from django.template.loader_tags import (BlockNode, ConstantIncludeNode, 
             IncludeNode) 


NEWLINES = re.compile(r'(\r\n|\r|\n)') 
INDENT = re.compile(r'(?:\r\n|\r|\n)([\ \t]+)') 


def get_indent(text, i=0): 
    ''' 
    Depending on value of `i`, returns first or last indent 
    (or any other if `i` is something other than 0 or -1) 
    found in `text`. Indent is any sequence of tabs or spaces 
    preceded by a newline. 
    ''' 
    try: 
     return INDENT.findall(text)[i] 
    except IndexError: 
     pass 


def reindent(self, context): 
    bits = '' 
    for node in self: 
     if isinstance(node, Node): 
      bit = self.render_node(node, context) 
     else: 
      bit = node 
     text = force_text(bit) 

     # Remove one indentation level 
     if isinstance(node, BlockNode): 
      if INDENT.match(text): 
       indent = get_indent(text) 
       text = re.sub(r'(\r\n|\r|\n)' + indent, r'\1', text) 

     # Add one indentation level 
     if isinstance(node, (BlockNode, ConstantIncludeNode, IncludeNode)): 
      text = text.strip() 
      if '\r' in text or '\n' in text: 
       indent = get_indent(bits, -1) 
       if indent: 
        text = NEWLINES.sub(r'\1' + indent, text) 

     bits += text 

    return mark_safe(bits) 


# Monkey-patching Django class 
NodeList.render = reindent 
+0

私はかなり新しいdjangoですが、これを私のプロジェクトでどのように実装できるかの例を教えてください。 –

答えて

1

あなたは異なるNodeListを作成するために、クラスの継承を使用することができますが、それはおそらく別の端にいくつかのパッチ適用が必要になります。あなたの解決策は簡単で簡単です。

class MyNodeList(NodeList): 
    def render(self, context): 
     # call super if you require so 
     # your reindent functionality 
3

テンプレートレイヤーを変更するのは問題ありませんが、ドキュメント全体ではなくノードのレンダリングを処理するだけで最適です。私はwriting custom middlewareをお勧めします。あなたのプロジェクトは、htmlやcssページのレンダリングされた応答をきれいに印刷します。

あなたのミドルウェアはSimpleTemplateResponseオブジェクトを表示および更新するために使用されるべきprocess_template_responseを実装する必要があります。

  • は、応答が
  • レンダリングされた場合のいずれかによって、文書の種類を確認してください参照してくださいis_rendered属性を確認してください:
    • template_name属性
    • の最後に目的のファイルの種類( .html.css)探しています
    • 古いが、再フォーマット
  • をインストールし、ゴージャスな見てあなたのレンダリングされたドキュメントを更新するためにcontent_type属性(ジャンゴ1.5)を見てみるか、おそらくmimetypeBeautiful SoupはHTMLのための素晴らしいですが、あなたはあなた兼ね備えを選択する必要がありますかわいいプリンターかあなた自身のロール)。

ミドルウェアは、最終的にはファイルに字句変更を加えないため、はるかに洗練されたソリューションだと思います。テンプレートの内容を決定するロジックから完全に切り離されています(ビジネスがない場合)。最後に、あなたのhtmlとcssのすべてが綺麗に見えるようにしたいのですが、なぜそれを最初の場所のテンプレートに結びつけるのですか?