web.pyソース分析:テンプレート(2)

9856 ワード

前の文章web.pyソース分析:テンプレート(1)はwebを説明した.pyのテンプレートの大まかな動作原理.本文は重点的にwebを述べる.pyテンプレートでサポートされている構文は、生成_をどのように変換するかです.template__で行ないます.
web.pyテンプレート構文と_template__()関数の対応関係
この章では、テンプレートの内容と変換後の_を示します.template__()関数の内容、および必要な文字の説明.テンプレートの名前はhelloに統一されています.html.
じゅんもじれつ
テンプレートの内容
hello, world

関数の内容
def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'hello, world
']) return self

def with
テンプレートの内容
$def with (name, value=[], *args, **kargs)
hello, $name

関数の内容
def __template__ (name, value=[], *args, **kargs):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'hello, ', escape_(name, True), u'
']) return self

生成された関数からdef with構文が生成するのは__であることがわかる.template__()関数のパラメータのリスト.
式の置換
テンプレートの内容
$def with (name, value)
$name
${name + value}
$(name + value)ing.
$name[value].function()

関数の内容
def __template__ (name, value):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u'
']) extend_([escape_((name + value), True), u'
']) extend_([escape_((name + value), True), u'ing.
']) extend_([escape_(name[value].function(), True), u'
']) return self

式の置換は式(式に対応するコード)を実行し、結果をTemplateResultインスタンスに追加します.
に値を付ける
テンプレートの内容
$def with (name, func)
$ name1 = name
$ name2 = func()

関数の内容
def __template__ (name, func):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    name1 = name
    name2 = func()

    return self

実は、変換後はPythonコードの付与文です.
コンテンツフィルタ
テンプレートの内容
$def with (name)
$name
$:name

関数の内容
def __template__ (name):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u'
']) extend_([escape_(name, False), u'
']) return self

生成されたコードから、フィルタ構文を使用するかどうかの違いはexcape_への転送です.関数の2番目のパラメータですが、この関数は実際には文字列処理関数にすぎません.後で話します.
テンプレートコード断行(newline suppression)
テンプレートの内容
$def with (name, func)
$name
hello, \
$name \
!
$func(1, 2, 3, 4, 5)

関数の内容
def __template__ (name, func):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u'
']) extend_([u'hello, ']) extend_([escape_(name, True), u' ']) extend_([u'!
']) extend_([escape_(func(1, 2, 3, 4, 5), True), u'
']) return self

結果として、テンプレート内のブレークラインは、結果に余分な改行を挿入しないようにするためだけです.また、1つの式の中間では断行はサポートされていません.たとえば、テンプレートでfunc関数のパラメータリストを2行に書くことはできません.
$記号
テンプレートの内容
$$

関数の内容
def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'$', u'
']) return self

コメント
テンプレートの内容
$# comment line
hello, world.

関数の内容
def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'
']) extend_([u'hello, world.
']) return self

テンプレート内のコメントの行は、生成された関数に1つの改行文字しかありません.
せいぎょこうぞう
forサイクル
テンプレートの内容
$for i in range(10):
    I like $i

関数の内容
def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    for i in loop.setup(range(10)):
        extend_([u'I like ', escape_(i, True), u'
']) return self

テンプレート内のforループはコード内のforループに変換され,変数loop(ForLoopオブジェクトは後で見る)が用いられる.
whileサイクル
テンプレートの内容
$def with (name_list)

$while name_list:
    hello, $name_list.pop()

関数の内容
def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'
']) while name_list: extend_([u'hello, ', escape_(name_list.pop(), True), u'
']) return self

注意forループとの違いはloop変数は使用されていません.
forサイクルのloop変数
テンプレートの内容
$def with (name_list)
$for name in name_list:
    $loop.index
    $loop.index0
    $loop.first
    $loop.last
    $loop.odd
    $loop.even
    $loop.parity
    $loop.parent
    hello, $name

$for i in range(10):
    $for name in name_list:
        $loop.parent
        hello, $name

関数の内容
def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    for name in loop.setup(name_list):
        extend_([escape_(loop.index, True), u'
']) extend_([escape_(loop.index0, True), u'
']) extend_([escape_(loop.first, True), u'
']) extend_([escape_(loop.last, True), u'
']) extend_([escape_(loop.odd, True), u'
']) extend_([escape_(loop.even, True), u'
']) extend_([escape_(loop.parity, True), u'
']) extend_([escape_(loop.parent, True), u'
']) extend_([u'hello, ', escape_(name, True), u'
']) extend_([u'
']) for i in loop.setup(range(10)): for name in loop.setup(name_list): extend_([escape_(loop.parent, True), u'
']) extend_([u'hello, ', escape_(name, True), u'
']) return self

ここではloop変数のメンバーとネストループの使用を示します.
if-else
テンプレートの内容
$def with (name_list)
$if name_list:
    $len(name_list)
$else:
    0

関数の内容
def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    if name_list:
        extend_([escape_(len(name_list), True), u'
']) else: extend_([u'0
']) return self

Elif文もサポートされています.
関数の定義
テンプレートの内容
$def with (name_list)

$def hello(name):
    hello, $name

$def hello_to_all(nlist):
    $for each in nlist:
        $hello(each)

$hello_to_all(name_list)

関数の内容
def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'
']) __lineoffset__ -= 3 def hello(name): self = TemplateResult(); extend_ = self.extend extend_([u'hello, ', escape_(name, True), u'
']) extend_([u'
']) return self __lineoffset__ -= 3 def hello_to_all(nlist): self = TemplateResult(); extend_ = self.extend for each in loop.setup(nlist): extend_([escape_(hello(each), True), u'
']) extend_([u'
']) return self extend_([escape_(hello_to_all(name_list), True), u'
']) return self

テンプレートによる関数のサポートは、内部関数を定義して呼び出し、各内部関数の戻り結果もTemplateResultインスタンスです.
code
テンプレートの内容
$def with (name_list)

$code:
  new_list = [x.upper() for x in name_list]
  def hello(name):
      return "hello, %s" % (name)

  more_new_list = []
  for each in new_list:
      more_new_list.append(hello(each))

$hello("everybody")
$len(more_new_list)

関数の内容
def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u'
']) new_list = [x.upper() for x in name_list] def hello(name): return "hello, %s" % (name) more_new_list = [] for each in new_list: more_new_list.append(hello(each)) extend_([escape_(hello("everybody"), True), u'
']) extend_([escape_(len(more_new_list), True), u'
']) return self

codeの構文は少し複雑で、その内部は元のPythonコードを定義するために使用され、以下のいくつかの特徴があります.
  • code内部定義の関数も内部関数であり、テンプレートの他の場所で呼び出すことができますが、結果はTemplateResultインスタンスに格納されません.
  • codeで定義された変数はすべて_として使用されます.template__()関数のローカル変数は、テンプレートの他の場所で呼び出すことができます.

  • codeブロックではprint文を使用して出力を印刷しないでください(デフォルトでは禁止されていますが).
    var
    テンプレートの内容
    $def with (name_list)
    $var title: hi
    $var title2: "hi"
    $var name: $name_list[0]
    $var name2: name_list[0]
    

    関数の内容
    def __template__ (name_list):
        __lineoffset__ = -4
        loop = ForLoop()
        self = TemplateResult(); extend_ = self.extend
        self['title'] = join_(u'hi')
        self['title2'] = join_(u'"hi"')
        self['name'] = join_(escape_(name_list[0], True))
        self['name2'] = join_(u'name_list[0]')
    
        return self
    

    varはテンプレートのプロパティを設定するために使用され、生成されたコードから見るとTemplateResultインスタンスのプロパティを設定します.上のテンプレートの内容には、いくつかの重要な詳細があります.
  • var name:valueのコロンの後ろの内容はデフォルトで文字列として処理され、引用符を付けなくてもよく、引用符を付けた場合、引用符も内容の一部として扱われます.
  • コロンの後に変数値にアクセスするには、$接頭辞を使用します.

  • まとめ
    これらのwebを書きました.pyテンプレートがサポートする構文と生成されたコードの対応関係は,テンプレートの構文を理解し,各構文の用途を理解し,ピットを踏まないようにするのに役立つことを望んでいる.