Django/テンプレートシステムを読む(レンダリング)
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Djangoを読む]]
#contents
*はじめに [#b440516d]
テンプレートの解析まで読んだので最後、いよいよテンプレー...
#code(Python){{
def render_to_string(template_name, context=None, request...
"""
Loads a template and renders it with a context. Retur...
template_name may be a string or a list of strings.
"""
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=u...
else:
template = get_template(template_name, using=using)
return template.render(context, request)
}}
templateの型は、とりあえずdjango.template.backends.django...
*Template移譲の終点探し [#v2225006]
とりあえずと言ったのは、templateと名のつくクラスが複数い...
#code(Python){{
def render(self, context=None, request=None):
context = make_context(context, request, autoesca...
try:
return self.template.render(context)
except TemplateDoesNotExist as exc:
reraise(exc, self.backend)
}}
ここでいうself.templateはこう渡されている。
#code(Python){{
def get_template(self, template_name):
try:
return Template(self.engine.get_template(temp...
except TemplateDoesNotExist as exc:
reraise(exc, self)
}}
たびたび見ているように、self.engineはdjango.template.engi...
#code(Python){{
def get_template(self, template_name):
"""
Returns a compiled Template object for the given ...
handling template inheritance recursively.
"""
template, origin = self.find_template(template_na...
if not hasattr(template, 'render'):
# template needs to be compiled
template = Template(template, origin, templat...
return template
}}
前回見た感じでは、find_templateの時点でコンパイルされたも...
*django.template.base.Template [#b2ebf392]
というわけでdjango.template.base.Templateのrenderメソッド
#code(Python){{
def render(self, context):
"Display stage -- can be called many times"
context.render_context.push()
try:
if context.template is None:
with context.bind_template(self):
context.template_name = self.name
return self._render(context)
else:
return self._render(context)
finally:
context.render_context.pop()
}}
contextでいろいろやっているのは見ててそんなにおもしろくな...
_renderはnodelist呼んでいるだけ。
#code(Python){{
def _render(self, context):
return self.nodelist.render(context)
}}
NodeListのrender
#code(Python){{
def render(self, context):
bits = []
for node in self:
if isinstance(node, Node):
bit = node.render_annotated(context)
else:
bit = node
bits.append(force_text(bit))
return mark_safe(''.join(bits))
}}
in selfとなっているのは、NodeListがlistクラスを継承してい...
render_annotatedというのは例外時にデバッグ情報出すように...
*VariableNode [#q62e4ac0]
変数を見てみましょう。ちなみに、Djangoテンプレートの変数...
-変数を辞書とみなし、「.」以下を辞書のキーとしてアクセス...
-変数の属性としてアクセスしてみる
-リストのインデックスとしてアクセスしてみる
-いずれの場合も、得られたものがcallableなら引数なしで呼び...
で、VariableNodeのrender
#code(Python){{
def render(self, context):
try:
output = self.filter_expression.resolve(conte...
except UnicodeDecodeError:
# Unicode conversion can fail sometimes for r...
# control (e.g. exception rendering). In that...
# quietly.
return ''
return render_value_in_context(output, context)
}}
FilterExpressionクラスのresolveメソッド
#code(Python){{
def resolve(self, context, ignore_failures=False):
if isinstance(self.var, Variable):
try:
obj = self.var.resolve(context)
except VariableDoesNotExist:
# 省略
else:
obj = self.var
# フィルターの処理省略
return obj
}}
varはVariableオブジェクトなのでVariableクラスのresolveへ。
#code(Python){{
def resolve(self, context):
"""Resolve this variable against a given context....
if self.lookups is not None:
# We're dealing with a variable that needs to...
value = self._resolve_lookup(context)
else:
# We're dealing with a literal, so it's alrea...
value = self.literal
if self.translate:
# 省略
return value
}}
前回見てなかったけど、lookupsはコンストラクタで設定される...
#code(Python){{
def _resolve_lookup(self, context):
current = context
try: # catch-all for silent variable failures
for bit in self.lookups:
try: # dictionary lookup
current = current[bit]
# ValueError/IndexError are for numpy...
# numpy < 1.9 and 1.9+ respectively
except (TypeError, AttributeError, KeyErr...
try: # attribute lookup
# Don't return class attributes i...
if isinstance(current, BaseContex...
raise AttributeError
current = getattr(current, bit)
except (TypeError, AttributeError) as...
# Reraise an AttributeError raise...
if (isinstance(e, AttributeError)...
not isinstance(current, B...
raise
try: # list-index lookup
current = current[int(bit)]
except (IndexError, # list index...
ValueError, # invalid li...
KeyError, # current is...
TypeError): # unsubscrip...
raise VariableDoesNotExist("F...
"[...
(b...
if callable(current):
if getattr(current, 'do_not_call_in_t...
pass
elif getattr(current, 'alters_data', ...
current = context.template.engine...
else:
try: # method call (assuming no ...
current = current()
except TypeError:
try:
inspect.getcallargs(curre...
except TypeError: # argument...
current = context.templat...
else:
raise
except Exception as e:
# 省略
return current
}}
ちょっと長いですが初めに挙げた順番で変数解決を行っていま...
ちなみに、「.」付きじゃない普通の変数の場合どう動くんだ?...
*django.template.defaulttags.IfNode [#f7dd39ca]
次にタグの処理を見てみましょう。前回も確認したifに対応す...
#code(Python){{
def render(self, context):
for condition, nodelist in self.conditions_nodeli...
if condition is not None: # if / el...
try:
match = condition.eval(context)
except VariableDoesNotExist:
match = None
else: # else cl...
match = True
if match:
return nodelist.render(context)
return ''
}}
conditionの中身がどうなっているかは前回さくっと省略しまし...
*おわりに [#r0a1b5fa]
以上、テンプレートのレンダリングについて見てきました。い...
さて、これでようやく一年ぐらいかけて読んできた(読んでな...
View(普通のMVCのController)、Model、Template(普通のMVC...
いろいろなケースをすべて対応するとなると結局ひとつの言語...
そういえばそろそろ2.0リリースされそうですね(笑)
終了行:
[[Djangoを読む]]
#contents
*はじめに [#b440516d]
テンプレートの解析まで読んだので最後、いよいよテンプレー...
#code(Python){{
def render_to_string(template_name, context=None, request...
"""
Loads a template and renders it with a context. Retur...
template_name may be a string or a list of strings.
"""
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=u...
else:
template = get_template(template_name, using=using)
return template.render(context, request)
}}
templateの型は、とりあえずdjango.template.backends.django...
*Template移譲の終点探し [#v2225006]
とりあえずと言ったのは、templateと名のつくクラスが複数い...
#code(Python){{
def render(self, context=None, request=None):
context = make_context(context, request, autoesca...
try:
return self.template.render(context)
except TemplateDoesNotExist as exc:
reraise(exc, self.backend)
}}
ここでいうself.templateはこう渡されている。
#code(Python){{
def get_template(self, template_name):
try:
return Template(self.engine.get_template(temp...
except TemplateDoesNotExist as exc:
reraise(exc, self)
}}
たびたび見ているように、self.engineはdjango.template.engi...
#code(Python){{
def get_template(self, template_name):
"""
Returns a compiled Template object for the given ...
handling template inheritance recursively.
"""
template, origin = self.find_template(template_na...
if not hasattr(template, 'render'):
# template needs to be compiled
template = Template(template, origin, templat...
return template
}}
前回見た感じでは、find_templateの時点でコンパイルされたも...
*django.template.base.Template [#b2ebf392]
というわけでdjango.template.base.Templateのrenderメソッド
#code(Python){{
def render(self, context):
"Display stage -- can be called many times"
context.render_context.push()
try:
if context.template is None:
with context.bind_template(self):
context.template_name = self.name
return self._render(context)
else:
return self._render(context)
finally:
context.render_context.pop()
}}
contextでいろいろやっているのは見ててそんなにおもしろくな...
_renderはnodelist呼んでいるだけ。
#code(Python){{
def _render(self, context):
return self.nodelist.render(context)
}}
NodeListのrender
#code(Python){{
def render(self, context):
bits = []
for node in self:
if isinstance(node, Node):
bit = node.render_annotated(context)
else:
bit = node
bits.append(force_text(bit))
return mark_safe(''.join(bits))
}}
in selfとなっているのは、NodeListがlistクラスを継承してい...
render_annotatedというのは例外時にデバッグ情報出すように...
*VariableNode [#q62e4ac0]
変数を見てみましょう。ちなみに、Djangoテンプレートの変数...
-変数を辞書とみなし、「.」以下を辞書のキーとしてアクセス...
-変数の属性としてアクセスしてみる
-リストのインデックスとしてアクセスしてみる
-いずれの場合も、得られたものがcallableなら引数なしで呼び...
で、VariableNodeのrender
#code(Python){{
def render(self, context):
try:
output = self.filter_expression.resolve(conte...
except UnicodeDecodeError:
# Unicode conversion can fail sometimes for r...
# control (e.g. exception rendering). In that...
# quietly.
return ''
return render_value_in_context(output, context)
}}
FilterExpressionクラスのresolveメソッド
#code(Python){{
def resolve(self, context, ignore_failures=False):
if isinstance(self.var, Variable):
try:
obj = self.var.resolve(context)
except VariableDoesNotExist:
# 省略
else:
obj = self.var
# フィルターの処理省略
return obj
}}
varはVariableオブジェクトなのでVariableクラスのresolveへ。
#code(Python){{
def resolve(self, context):
"""Resolve this variable against a given context....
if self.lookups is not None:
# We're dealing with a variable that needs to...
value = self._resolve_lookup(context)
else:
# We're dealing with a literal, so it's alrea...
value = self.literal
if self.translate:
# 省略
return value
}}
前回見てなかったけど、lookupsはコンストラクタで設定される...
#code(Python){{
def _resolve_lookup(self, context):
current = context
try: # catch-all for silent variable failures
for bit in self.lookups:
try: # dictionary lookup
current = current[bit]
# ValueError/IndexError are for numpy...
# numpy < 1.9 and 1.9+ respectively
except (TypeError, AttributeError, KeyErr...
try: # attribute lookup
# Don't return class attributes i...
if isinstance(current, BaseContex...
raise AttributeError
current = getattr(current, bit)
except (TypeError, AttributeError) as...
# Reraise an AttributeError raise...
if (isinstance(e, AttributeError)...
not isinstance(current, B...
raise
try: # list-index lookup
current = current[int(bit)]
except (IndexError, # list index...
ValueError, # invalid li...
KeyError, # current is...
TypeError): # unsubscrip...
raise VariableDoesNotExist("F...
"[...
(b...
if callable(current):
if getattr(current, 'do_not_call_in_t...
pass
elif getattr(current, 'alters_data', ...
current = context.template.engine...
else:
try: # method call (assuming no ...
current = current()
except TypeError:
try:
inspect.getcallargs(curre...
except TypeError: # argument...
current = context.templat...
else:
raise
except Exception as e:
# 省略
return current
}}
ちょっと長いですが初めに挙げた順番で変数解決を行っていま...
ちなみに、「.」付きじゃない普通の変数の場合どう動くんだ?...
*django.template.defaulttags.IfNode [#f7dd39ca]
次にタグの処理を見てみましょう。前回も確認したifに対応す...
#code(Python){{
def render(self, context):
for condition, nodelist in self.conditions_nodeli...
if condition is not None: # if / el...
try:
match = condition.eval(context)
except VariableDoesNotExist:
match = None
else: # else cl...
match = True
if match:
return nodelist.render(context)
return ''
}}
conditionの中身がどうなっているかは前回さくっと省略しまし...
*おわりに [#r0a1b5fa]
以上、テンプレートのレンダリングについて見てきました。い...
さて、これでようやく一年ぐらいかけて読んできた(読んでな...
View(普通のMVCのController)、Model、Template(普通のMVC...
いろいろなケースをすべて対応するとなると結局ひとつの言語...
そういえばそろそろ2.0リリースされそうですね(笑)
ページ名: