2012-12-30 13 views
12

サガは、original threadから拡張されています。私はリストとして、またはdictsとして、単独でnamedtuplesを渡すJinja2テンプレートマクロ内の名前付きタプル

from flask import get_template_attribute 
from jinja2 import Template 

    class InternalMacro(object): 
     """ 
     Creates a macro given a name, internal macro text, and content to fill(as namedtuple(t.var), dict(k,v), list(i), or other) 
     """ 
     def __init__(self, name = None, 
          text = None, 
          content_is = None): 
      self.name = name 
      self.macro_name = "{}_template".format(self.name) 
      self.macro_var = "{}_macro".format(self.name) 
      self.text = text 
      self.content_is = content_is 
      self.macro_txt = self.format_text 

     @property 
     def is_tuple(self): 
      return "{{% macro {0}(t) %}}{1}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def is_dict(self): 
      return "{{% macro {0}(items) %}}{{% for k,v in items.iteritems() %}}{1}{{% endfor %}}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def is_list(self): 
      return "{{% macro {0}(items) %}}{{% for i in items %}}{1}{{% endfor %}}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def format_text(self): 
      return getattr(self, self.content_is) 

     @property 
     def return_template(self): 
      return Template(self.macro_txt) 

     @property 
     def return_callable(self): 
      return get_template_attribute(self.return_template, self.macro_var) 

だから、私は、Pythonのコード内でマクロを作るために何かを持っています。これはリストを渡すときに機能します(まだdictとして完全にテストされていませんが)。単一のnamedtupleを渡すときは機能しません。どんなものでも、今のところnamedtupleはUnicodeとしてエスケープされます。

だから、与えられた:

test_macro = InternalMacro('test', '{{ t }} <div id="divvy">{{ t.var }}</div>', 'is_tuple') 

test_macro.return_callable(Anamedtuple) 

リターン:

u'Anamedtuple(var="A VAR VALUE") <div id="divvy"></div>' 

ない:

u'Anamedtuple(var="A VAR VALUE")' <div id="divvy">A VAR VALUE</div> 

私はリストとしてこれを行う場合、通常、呼び出される.varを。

私は行方不明で、これを回避する方法は何ですか?単一のnamedtupleはエスケープされますが、リストはエスケープされません。私はリストとして単一のものをすることができ、最初のポップだけ、多分私には汚れているようです。これを改善するための提案も同様に評価されました。

EDIT:

簡単な解決策はただ単にまだ私はそこに何が起こっているかを把握したいと思います1のリストを渡し、単一およびdictのオプションを排除し、リストに渡されたすべてのものを削減することでした正確に。

EDIT2:

深い双方向I出力はnamedtupleは私がすなわち見ていた結果生成されたことを示した探検 - で

test_macro = InternalMacro('test', '{{ t }} <div id="divvy">{{ t.var }}</div>', 'is_tuple') 

結果:一方

u'Anamedtuple(var="A VAR VALUE") <div id="divvy"></div>' 

を:

test_macro = InternalMacro('test', '<div id="divvy">{{ t.var }}</div>', 'is_tuple') 

の結果は

'<div id="divvy">A VAR VALUE</div>' 

となります。指定されたタプルは一度読み込まれたと思います。

+0

を起こる、私はPython用シンボリックデバッガと自由な時間がたくさんあると考えているところ

env/Python27/lib/site-packages/jinja2/parser.pyがある、あなたは(1つの完全なファイルの例を投稿することができますという名前を含みますタプル)と私はそれをスピンします。 – David

答えて

1
あなたが望んでいないものをおそらく

けど...

from collections import namedtuple 

x = namedtuple("Foo", "var") 
z = x(var = 123) 
with app.app_context(): 
    test_macro = InternalMacro('test', "'{{ t }}' <div id=\"divvy\">{{ t.var }}</div>", 'is_tuple') 
    returnVal = test_macro.return_callable(z) 

print returnVal 
#'Foo(var=123)' &lt;div id="divvy"&gt;123&lt;/div&gt; 

'フー(VAR = 123')<のdiv idは=私は「/divの>

repr(returnVal) 
'u\'\\\'Foo(var=123)\\\' <div id="divvy">123</div>\'' 

"DIVVY" Python 2.7とFlask 0.10.1を使用しています(これはしばらくありました)。

ヒントは明示的に定義されていないものの期待です。私がそれを見逃していない限り、InternalMarcoのis_tuple()プロパティ内のどのような基本型(int、strなど)とクラスオブジェクトに差別はありません。また、is_tupleの場合、すべてが1つの文字列にまとめられ、バッファに出力されます。

for i in itemsの動作は、ループ本体{i}(タイプが{1}の場合)をフラッシュし、ストリングを追加しません。私はこれが

ライン#869

elif token.type == 'block_begin': 
    flush_data() 
    next(self.stream) 
    if end_tokens is not None and \ 
        self.stream.current.test_any(*end_tokens): 
    return body 
    rv = self.parse_statement() 
    if isinstance(rv, list): 
    body.extend(rv) 
    else: 
    body.append(rv) 
    self.stream.expect('block_end') 
関連する問題