<span id="vwo9i"></span>
      <li id="vwo9i"><meter id="vwo9i"></meter></li>

          <thead id="vwo9i"></thead>

          \n hello! {{ name }} \n <\/body> \n<\/html> <\/pre>\n<\/p>\n

           處理后
          \n<\/p>\n

          \n
          \n_buffer = [] \n_buffer.append('\\\\n\\\\n') \n \n_tmp = title \nif isinstance(_tmp, str): _buffer.append(_tmp) \nelif isinstance(_tmp, unicode): _buffer.append(_tmp.encode('utf-8')) \nelse: _buffer.append(str(_tmp)) \n \n_buffer.append('<\/title>\\\\n<\/head>\\\\n<body>
          <h1><a href="http://m.miracleart.cn/">国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂</a></h1>\\\\n') \n_buffer.append('hello! ') \n \n_tmp = name \nif isinstance(_tmp, str): _buffer.append(_tmp) \nelif isinstance(_tmp, unicode): _buffer.append(_tmp.encode('utf-8')) \nelse: _buffer.append(str(_tmp)) \n \n_buffer.append('\\\\n<\/body>\\\\n<\/html>\\\\n') \nreturn ''.join(_buffer)\\n\" \n<\/pre>\n<\/p>\n<p><\/p>\n<p><strong>實(shí)例剖析<br \/>\n<\/strong>tornado的模板基本都在template.py這個(gè)文件中,短短800多行代碼就實(shí)現(xiàn)了基本可用的模板,讓我們慢慢揭開她的面紗。<br \/>\n首先我們看看tornado是如何編譯模板的,下面是個(gè)簡單的模板<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nt = Template(\"\"\"\\ \n{%if names%} \n  {% for name in names %} \n    {{name}} \n  {%end%} \n{%else%} \nno one \n{%end%} \n\"\"\") \n<\/pre>\n<\/p>\n<p>tornado最后編譯代碼如下: <br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\ndef _tt_execute(): # <string>:0 \n  _tt_buffer = [] # <string>:0 \n  _tt_append = _tt_buffer.append # <string>:0 \n  if names: # <string>:1 \n    _tt_append('\\n  ') # <string>:2 \n    for name in names: # <string>:2 \n      _tt_append('\\n    ') # <string>:3 \n      _tt_tmp = name # <string>:3 \n      if isinstance(_tt_tmp, _tt_string_types): _tt_tmp = _tt_utf8(_tt_tmp) # <string>:3 \n      else: _tt_tmp = _tt_utf8(str(_tt_tmp)) # <string>:3 \n      _tt_tmp = _tt_utf8(xhtml_escape(_tt_tmp)) # <string>:3 \n      _tt_append(_tt_tmp) # <string>:3 \n      _tt_append('\\n  ') # <string>:4 \n      pass # <string>:2 \n    _tt_append('\\n') # <string>:5 \n    pass # <string>:5 \n  else: # <string>:5 \n    _tt_append('\\nno one\\n') # <string>:7 \n    pass # <string>:1 \n  _tt_append('\\n') # <string>:8 \n  return _tt_utf8('').join(_tt_buffer) # <string>:0 \n<\/pre>\n<\/p>\n<p>是的,你沒看錯(cuò),tornado編譯就是將之翻譯成一個(gè)個(gè)代碼塊,最后通exec傳遞我們給的參數(shù)命名空間執(zhí)行_tt_execute函數(shù)。<br \/>\n在我們上面的模板中包含了4種預(yù)定義的NODE節(jié)點(diǎn),_ControlBlock,_Expression,_TEXT,每種Node節(jié)點(diǎn)都有自己的生成方式。<br \/>\n比如說_Expression表達(dá)式節(jié)點(diǎn),也就是我們模板中的{{name}},當(dāng)_parse解析時(shí)發(fā)現(xiàn)'{'后面還是'{'就認(rèn)為是表達(dá)式節(jié)點(diǎn),<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass _Expression(_Node): \n  def __init__(self, expression, line, raw=False): \n    self.expression = expression \n    self.line = line \n    self.raw = raw \n \n  def generate(self, writer): \n    writer.write_line(\"_tt_tmp = %s\" % self.expression, self.line) \n    writer.write_line(\"if isinstance(_tt_tmp, _tt_string_types):\" \n             \" _tt_tmp = _tt_utf8(_tt_tmp)\", self.line) \n    writer.write_line(\"else: _tt_tmp = _tt_utf8(str(_tt_tmp))\", self.line) \n    if not self.raw and writer.current_template.autoescape is not None: \n      # In python3 functions like xhtml_escape return unicode, \n      # so we have to convert to utf8 again. \n      writer.write_line(\"_tt_tmp = _tt_utf8(%s(_tt_tmp))\" % \n               writer.current_template.autoescape, self.line) \n    writer.write_line(\"_tt_append(_tt_tmp)\", self.line) \n<\/pre>\n<\/p>\n<p>最后生成時(shí)會(huì)調(diào)用節(jié)點(diǎn)的generate方法,self.expression就是上面的name,所以當(dāng)exec的時(shí)候就會(huì)把name的值append到內(nèi)部的列表中。<br \/>\n像if,for等都是控制節(jié)點(diǎn),他們的定義如下: <br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass _ControlBlock(_Node): \n  def __init__(self, statement, line, body=None): \n    self.statement = statement \n    self.line = line \n    self.body = body \n \n  def each_child(self): \n    return (self.body,) \n \n  def generate(self, writer): \n    writer.write_line(\"%s:\" % self.statement, self.line) \n    with writer.indent(): \n      self.body.generate(writer) \n      # Just in case the body was empty \n      writer.write_line(\"pass\", self.line) <\/pre>\n<\/p>\n<p><br \/>\n控制節(jié)點(diǎn)的generate方法有點(diǎn)意義,因?yàn)閕f,for等是下一行是需要縮進(jìn)的,所以調(diào)用了with writer.indent繼續(xù)縮進(jìn)控制,可以看下<br \/>\n_CodeWriter的indent方法。<br \/>\n節(jié)點(diǎn)中比較有意思的是_ExtendsBlock,這是實(shí)現(xiàn)目標(biāo)基礎(chǔ)的節(jié)點(diǎn),<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass _ExtendsBlock(_Node): \n  def __init__(self, name): \n    self.name = name \n<\/pre>\n<\/p>\n<p>我們發(fā)現(xiàn)并沒有定義generate方法,那當(dāng)生成繼承節(jié)點(diǎn)時(shí)不是會(huì)報(bào)錯(cuò)嗎?讓我們看一段事例<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nloader = Loader('.') \nt=Template(\"\"\"\\ \n{% extends base.html %} \n{% block login_name %}hello world! {{ name }}{% end %} \n\"\"\",loader=loader) \n<\/pre>\n<\/p>\n<p>當(dāng)前目錄下base.html如下:<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\n<html>  \n<head>  \n<title>{{ title }}<\/title>  \n<\/head>  \n<body>  \n{% block login_name %}hello! {{ name }}{% end %}  \n<\/body>  \n<\/html> <\/pre>\n<\/p>\n<p> 我們可以看看解析后的節(jié)點(diǎn),<br \/>\n<\/p>\n<p><img alt=\"2016711182740215.jpg (706×500)\" src=\"http:\/\/files.jb51.net\/file_images\/article\/201607\/2016711182740215.jpg?2016611182750\" \/><\/p>\n<p>由于我們繼承了base.html,所以我們的應(yīng)該以base.html的模板生成,并使用新定義的block代替base.html中的block,<br \/>\n這是很正常的思路,tornado也的確是這么干的,只不過處理的并不是在_ExtendsBlock。<br \/>\n而實(shí)在Template的_generate_python中<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\ndef _generate_python(self, loader, compress_whitespace): \n   buffer = StringIO() \n   try: \n     # named_blocks maps from names to _NamedBlock objects \n     named_blocks = {} \n     ancestors = self._get_ancestors(loader) \n     ancestors.reverse() \n     for ancestor in ancestors: \n       ancestor.find_named_blocks(loader, named_blocks) \n     writer = _CodeWriter(buffer, named_blocks, loader, ancestors[0].template, \n               compress_whitespace) \n     ancestors[0].generate(writer) \n     return buffer.getvalue() \n   finally: \n     buffer.close() \n \n def _get_ancestors(self, loader): \n   ancestors = [self.file] \n   for chunk in self.file.body.chunks: \n     if isinstance(chunk, _ExtendsBlock): \n       if not loader: \n         raise ParseError(\"{% extends %} block found, but no \" \n                 \"template loader\") \n       template = loader.load(chunk.name, self.name) \n       ancestors.extend(template._get_ancestors(loader)) \n   return ancestors \n<\/pre>\n<\/p>\n<p>_generate_python中調(diào)用_get_ancestors獲取當(dāng)前模板的父模板,我們看到如果當(dāng)前模板的_FILE節(jié)點(diǎn)中有_ExtendsBlock就代表有父模板并通過loader.load加載父模板,此時(shí)父模板已經(jīng)是解析過的_FILE節(jié)點(diǎn)了。所以,在上面的模板中,ancestors是[當(dāng)前模板_FILE節(jié)點(diǎn),父模板_FILE節(jié)點(diǎn)],ancestors.reverse()后其實(shí)ancestors[0]就是父模板,我們看到最后是通過ancestors[0].generate(writer)來生成代碼的。那當(dāng)前模板是如何替換父模板的block內(nèi)容呢?<br \/>\n看上圖,block login_name通過解析為_NamedBlock,在_generate_python中通過調(diào)用ancestor.find_named_blocks來替換<br \/>\n父模板的_NamedBlock的。<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nfor ancestor in ancestors:\n    ancestor.find_named_blocks(loader, named_blocks)\nancestor其實(shí)就是_FILE節(jié)點(diǎn),find_named_blocks將遍歷_FILE節(jié)點(diǎn)中所有節(jié)點(diǎn)并調(diào)用find_named_blocks\n \nclass _NamedBlock(_Node): \n  def find_named_blocks(self, loader, named_blocks): \n    named_blocks[self.name] = self \n    _Node.find_named_blocks(self, loader, named_blocks) \n<\/pre>\n<\/p>\n<p>其它節(jié)點(diǎn)find_named_blocks都沒有做什么事,_NamedBlock通過named_blocks[self.name] = self替換為當(dāng)前模板的_NamedBlock,因?yàn)閍ncestors父模板在前,當(dāng)前模板在后,所以最后使用的是當(dāng)前模板的_NamedBlock。<br \/>\n生成代碼后generate將在給定的命名空間中exec代碼<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\ndef generate(self, **kwargs): \n  \"\"\"Generate this template with the given arguments.\"\"\" \n  namespace = { \n    \"escape\": escape.xhtml_escape, \n    \"xhtml_escape\": escape.xhtml_escape, \n    \"url_escape\": escape.url_escape, \n    \"json_encode\": escape.json_encode, \n    \"squeeze\": escape.squeeze, \n    \"linkify\": escape.linkify, \n    \"datetime\": datetime, \n    \"_tt_utf8\": escape.utf8, # for internal use \n    \"_tt_string_types\": (unicode_type, bytes_type), \n    # __name__ and __loader__ allow the traceback mechanism to find \n    # the generated source code. \n    \"__name__\": self.name.replace('.', '_'), \n    \"__loader__\": ObjectDict(get_source=lambda name: self.code), \n  } \n  namespace.update(self.namespace) \n  namespace.update(kwargs) \n  exec_in(self.compiled, namespace) \n  execute = namespace[\"_tt_execute\"] \n  # Clear the traceback module's cache of source data now that \n  # we've generated a new template (mainly for this module's \n  # unittests, where different tests reuse the same name). \n  linecache.clearcache() \n  return execute() \n<\/pre>\n<\/p>\n<p>所以在模板中可以使用datetime等,都是通過在這里注入到模板中的,當(dāng)然還有其它的是通過<br \/>\nweb.py 中g(shù)et_template_namespace注入的 <br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\n def get_template_namespace(self): \n   \"\"\"Returns a dictionary to be used as the default template namespace. \n \n   May be overridden by subclasses to add or modify values. \n \n   The results of this method will be combined with additional \n   defaults in the `tornado.template` module and keyword arguments \n   to `render` or `render_string`. \n   \"\"\" \n   namespace = dict( \n     handler=self, \n     request=self.request, \n     current_user=self.current_user, \n     locale=self.locale, \n     _=self.locale.translate, \n     static_url=self.static_url, \n     xsrf_form_html=self.xsrf_form_html, \n     reverse_url=self.reverse_url \n   ) \n   namespace.update(self.ui) \n   return namespace \n<\/pre>\n<\/p>\n<p>我們再來看看tornado的模板是如何對UI模塊的支持的。<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\n{% for entry in entries %} \n {% module Entry(entry) %} \n{% end %} \n<\/pre>\n<\/p>\n<p>在使用module時(shí)將會(huì)生成_Module節(jié)點(diǎn) <br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass _Module(_Expression): \n  def __init__(self, expression, line): \n    super(_Module, self).__init__(\"_tt_modules.\" + expression, line, \n                   raw=True) \n<\/pre>\n<\/p>\n<p>我們看到其實(shí)_Module節(jié)點(diǎn)是繼承自_Expression節(jié)點(diǎn),所以最后執(zhí)行的是_tt_modules.Entry(entry)<br \/>\n_tt_modules定義在web.py的RequestHandler中<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nself.ui[\"_tt_modules\"] = _UIModuleNamespace(self,application.ui_modules)\n<\/pre>\n<\/p>\n<p>并通過上文的get_template_namespace中注入到模板中。<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass _UIModuleNamespace(object): \n  \"\"\"Lazy namespace which creates UIModule proxies bound to a handler.\"\"\" \n  def __init__(self, handler, ui_modules): \n    self.handler = handler \n    self.ui_modules = ui_modules \n \n  def __getitem__(self, key): \n    return self.handler._ui_module(key, self.ui_modules[key]) \n \n  def __getattr__(self, key): \n    try: \n      return self[key] \n    except KeyError as e: \n      raise AttributeError(str(e)) \n<\/pre>\n<\/p>\n<p>所以當(dāng)執(zhí)行_tt_modules.Entry(entry)時(shí)先訪問_UIModuleNamespace的__getattr__,后訪問__getitem__,最后調(diào)用<br \/>\nhandler._ui_module(key, self.ui_modules[key]),<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\ndef _ui_module(self, name, module): \n  def render(*args, **kwargs): \n    if not hasattr(self, \"_active_modules\"): \n      self._active_modules = {} \n    if name not in self._active_modules: \n      self._active_modules[name] = module(self) \n    rendered = self._active_modules[name].render(*args, **kwargs) \n    return rendered \n  return render \n<\/pre>\n<\/p>\n<p>_tt_modules.Entry(entry)中entry將會(huì)傳給_ui_module內(nèi)部的render,也就是args=entry<br \/>\nself._active_modules[name] = module(self)此時(shí)就是實(shí)例化后的UIModule,調(diào)用render獲取渲染后的內(nèi)容<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass Entry(tornado.web.UIModule): \n  def render(self, entry, show_comments=False): \n    return self.render_string( \n      \"module-entry.html\", entry=entry, show_comments=show_comments) <\/pre>\n<\/p>\n<p>當(dāng)然如果你覺得這么做費(fèi)事,也可以使用tornado自帶的TemplateModule,它繼承自UIModule,<br \/>\n你可以這么用<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\n{% module Template(\"module-entry.html\", show_comments=True) %} \n<\/pre>\n<\/p>\n<p>在module_entry.html中可以通過set_resources引用需要的靜態(tài)文件<br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\n{{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\") }} \n<\/pre>\n<\/p>\n<p>這里需要注意的是:只能在Template引用的html文件中使用set_resources函數(shù),因?yàn)閟et_resources是TemplateModule.render的內(nèi)部函數(shù) <br \/>\n<\/p>\n<div   id="377j5v51b"   class=\"jb51code\">\n<pre class='brush:php;toolbar:false;'>\nclass TemplateModule(UIModule): \n  \"\"\"UIModule that simply renders the given template. \n \n  {% module Template(\"foo.html\") %} is similar to {% include \"foo.html\" %}, \n  but the module version gets its own namespace (with kwargs passed to \n  Template()) instead of inheriting the outer template's namespace. \n \n  Templates rendered through this module also get access to UIModule's \n  automatic javascript\/css features. Simply call set_resources \n  inside the template and give it keyword arguments corresponding to \n  the methods on UIModule: {{ set_resources(js_files=static_url(\"my.js\")) }} \n  Note that these resources are output once per template file, not once \n  per instantiation of the template, so they must not depend on \n  any arguments to the template. \n  \"\"\" \n  def __init__(self, handler): \n    super(TemplateModule, self).__init__(handler) \n    # keep resources in both a list and a dict to preserve order \n    self._resource_list = [] \n    self._resource_dict = {} \n \n  def render(self, path, **kwargs): \n    def set_resources(**kwargs): \n      if path not in self._resource_dict: \n        self._resource_list.append(kwargs) \n        self._resource_dict[path] = kwargs \n      else: \n        if self._resource_dict[path] != kwargs: \n          raise ValueError(\"set_resources called with different \" \n                   \"resources for the same template\") \n      return \"\" \n    return self.render_string(path, set_resources=set_resources, \n                 **kwargs) <\/pre>\n\n<p><\/p>\n\n<\/div>"}	</script>
          	
          <meta http-equiv="Cache-Control" content="no-transform" />
          <meta http-equiv="Cache-Control" content="no-siteapp" />
          <script>var V_PATH="/";window.onerror=function(){ return true; };</script>
          </head>
          
          <body data-commit-time="2023-12-28T14:50:12+08:00" class="editor_body body2_2">
          	<link rel="stylesheet" type="text/css" href="/static/csshw/stylehw.css">
          <header>
              <div   id="377j5v51b"   class="head">
                  <div   id="377j5v51b"   class="haed_left">
                      <div   id="377j5v51b"   class="haed_logo">
                          <a href="http://m.miracleart.cn/de/" title="" class="haed_logo_a">
                              <img src="/static/imghw/logo.png" alt="" class="haed_logoimg">
                          </a>
                      </div>
                      <div   id="377j5v51b"   class="head_nav">
                          <div   id="377j5v51b"   class="head_navs">
                              <a href="javascript:;" title="Gemeinschaft" class="head_nava head_nava-template1">Gemeinschaft</a>
                              <div   class="377j5v51b"   id="dropdown-template1" style="display: none;">
                                  <div   id="377j5v51b"   class="languagechoose">
                                      <a href="http://m.miracleart.cn/de/article.html" title="Artikel" class="languagechoosea on">Artikel</a>
                                      <a href="http://m.miracleart.cn/de/faq/zt" title="Themen" class="languagechoosea">Themen</a>
                                      <a href="http://m.miracleart.cn/de/wenda.html" title="Fragen und Antworten" class="languagechoosea">Fragen und Antworten</a>
                                  </div>
                              </div>
                          </div>
          
                          <div   id="377j5v51b"   class="head_navs">
                              <a href="javascript:;" title="Lernen" class="head_nava head_nava-template1_1">Lernen</a>
                              <div   class="377j5v51b"   id="dropdown-template1_1" style="display: none;">
                                  <div   id="377j5v51b"   class="languagechoose">
                                      <a href="http://m.miracleart.cn/de/course.html" title="Kurs" class="languagechoosea on">Kurs</a>
                                      <a href="http://m.miracleart.cn/de/dic/" title="Programmierw?rterbuch" class="languagechoosea">Programmierw?rterbuch</a>
                                  </div>
                              </div>
                          </div>
          
                          <div   id="377j5v51b"   class="head_navs">
                              <a href="javascript:;" title="Tools-Bibliothek" class="head_nava head_nava-template1_2">Tools-Bibliothek</a>
                              <div   class="377j5v51b"   id="dropdown-template1_2" style="display: none;">
                                  <div   id="377j5v51b"   class="languagechoose">
                                      <a href="http://m.miracleart.cn/de/toolset/development-tools" title="Entwicklungswerkzeuge" class="languagechoosea on">Entwicklungswerkzeuge</a>
                                      <a href="http://m.miracleart.cn/de/toolset/website-source-code" title="Quellcode der Website" class="languagechoosea">Quellcode der Website</a>
                                      <a href="http://m.miracleart.cn/de/toolset/php-libraries" title="PHP-Bibliotheken" class="languagechoosea">PHP-Bibliotheken</a>
                                      <a href="http://m.miracleart.cn/de/toolset/js-special-effects" title="JS-Spezialeffekte" class="languagechoosea on">JS-Spezialeffekte</a>
                                      <a href="http://m.miracleart.cn/de/toolset/website-materials" title="Website-Materialien" class="languagechoosea on">Website-Materialien</a>
                                      <a href="http://m.miracleart.cn/de/toolset/extension-plug-ins" title="Erweiterungs-Plug-Ins" class="languagechoosea on">Erweiterungs-Plug-Ins</a>
                                  </div>
                              </div>
                          </div>
          
                          <div   id="377j5v51b"   class="head_navs">
                              <a href="http://m.miracleart.cn/de/ai" title="KI-Tools" class="head_nava head_nava-template1_3">KI-Tools</a>
                          </div>
          
                          <div   id="377j5v51b"   class="head_navs">
                              <a href="javascript:;" title="Freizeit" class="head_nava head_nava-template1_3">Freizeit</a>
                              <div   class="377j5v51b"   id="dropdown-template1_3" style="display: none;">
                                  <div   id="377j5v51b"   class="languagechoose">
                                      <a href="http://m.miracleart.cn/de/game" title="Spiel-Download" class="languagechoosea on">Spiel-Download</a>
                                      <a href="http://m.miracleart.cn/de/mobile-game-tutorial/" title="Spiel-Tutorials" class="languagechoosea">Spiel-Tutorials</a>
          
                                  </div>
                              </div>
                          </div>
                      </div>
                  </div>
                              <div   id="377j5v51b"   class="head_search">
                          <input id="key_words"  onkeydown="if (event.keyCode == 13) searchs('de')" class="search-input" type="text" autocomplete="off" name="keywords" required="required" placeholder="Block,address,transaction,news" value="">
                          <a href="javascript:;" title="suchen"  onclick="searchs('de')"><img src="/static/imghw/find.png" alt="suchen"></a>
                      </div>
                          <div   id="377j5v51b"   class="head_right">
                      <div   id="377j5v51b"   class="haed_language">
                          <a href="javascript:;" class="layui-btn haed_language_btn">Deutsch<i class="layui-icon layui-icon-triangle-d"></i></a>
                          <div   class="377j5v51b"   id="dropdown-template" style="display: none;">
                              <div   id="377j5v51b"   class="languagechoose">
                                                          <a href="javascript:setlang('zh-cn');" title="簡體中文" class="languagechoosea">簡體中文</a>
                                                          <a href="javascript:setlang('en');" title="English" class="languagechoosea">English</a>
                                                          <a href="javascript:setlang('zh-tw');" title="繁體中文" class="languagechoosea">繁體中文</a>
                                                          <a href="javascript:setlang('ja');" title="日本語" class="languagechoosea">日本語</a>
                                                          <a href="javascript:setlang('ko');" title="???" class="languagechoosea">???</a>
                                                          <a href="javascript:setlang('ms');" title="Melayu" class="languagechoosea">Melayu</a>
                                                          <a href="javascript:setlang('fr');" title="Fran?ais" class="languagechoosea">Fran?ais</a>
                                                          <a href="javascript:;" title="Deutsch" class="languagechoosea">Deutsch</a>
                                                      </div>
                          </div>
                      </div>
                      <span id="377j5v51b"    class="head_right_line"></span>
                                      <div style="display: block;" id="login" class="haed_login ">
                              <a href="javascript:;"  title="Login" class="haed_logina ">Login</a>
                          </div>
                          <div style="display: block;" id="reg" class="head_signup login">
                              <a href="javascript:;"  title="singup" class="head_signupa">singup</a>
                          </div>
                      
                  </div>
              </div>
          </header>
          
          	
          	<main>
          		<div   id="377j5v51b"   class="Article_Details_main">
          			<div   id="377j5v51b"   class="Article_Details_main1">
          							<div   id="377j5v51b"   class="Article_Details_main1M">
          					<div   id="377j5v51b"   class="phpgenera_Details_mainL1">
          						<a href="http://m.miracleart.cn/de/" title="Heim"
          							class="phpgenera_Details_mainL1a">Heim</a>
          						<img src="/static/imghw/top_right.png" alt="" />
          												<a href="http://m.miracleart.cn/de/be/"
          							class="phpgenera_Details_mainL1a">Backend-Entwicklung</a>
          						<img src="/static/imghw/top_right.png" alt="" />
          												<a href="http://m.miracleart.cn/de/python-tutorials.html"
          							class="phpgenera_Details_mainL1a">Python-Tutorial</a>
          						<img src="/static/imghw/top_right.png" alt="" />
          						<span>Eine eingehende Analyse der in Pythons Tornado-Framework integrierten Template-Engine</span>
          					</div>
          					
          					<div   id="377j5v51b"   class="Articlelist_txts">
          						<div   id="377j5v51b"   class="Articlelist_txts_info">
          							<h1 class="Articlelist_txts_title">Eine eingehende Analyse der in Pythons Tornado-Framework integrierten Template-Engine</h1>
          							<div   id="377j5v51b"   class="Articlelist_txts_info_head">
          								<div   id="377j5v51b"   class="author_info">
          									<a href="http://m.miracleart.cn/de/member/887227.html"  class="author_avatar">
          									<img class="lazy"  data-src="https://img.php.cn/upload/avatar/000/887/227/63bb7851c9547215.jpg" src="/static/imghw/default1.png" alt="WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB">
          									</a>
          									<div   id="377j5v51b"   class="author_detail">
          																			<a href="http://m.miracleart.cn/de/member/887227.html" class="author_name">WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB</a>
                                          										</div>
          								</div>
                          			</div>
          							<span id="377j5v51b"    class="Articlelist_txts_time">Aug 04, 2016 am	 08:55 AM</span>
          															<div   id="377j5v51b"   class="Articlelist_txts_infos">
          																			<span id="377j5v51b"    class="Articlelist_txts_infoss on">python</span>
          																			<span id="377j5v51b"    class="Articlelist_txts_infoss ">tornado</span>
          																			<span id="377j5v51b"    class="Articlelist_txts_infoss ">Vorlage</span>
          																	</div>
          														
          						</div>
          					</div>
          					<hr />
          					<div   id="377j5v51b"   class="article_main php-article">
          						<div   id="377j5v51b"   class="article-list-left detail-content-wrap content">
          						<ins class="adsbygoogle"
          							style="display:block; text-align:center;"
          							data-ad-layout="in-article"
          							data-ad-format="fluid"
          							data-ad-client="ca-pub-5902227090019525"
          							data-ad-slot="3461856641">
          						</ins>
          						
          
          					<p>template中的_parse方法是模板文法的解析器,而這個(gè)文件中一坨一坨的各種node以及block,就是解析結(jié)果的承載者,也就是說在經(jīng)過parse處理過后,我們輸入的tornado的html模板就變成了各種block的集合。<br>
          這些block和node的祖宗就是這個(gè)“抽象”類, _Node,它定義了三個(gè)方法定義,其中g(shù)enerate方法是必須由子類提供實(shí)現(xiàn)的(所以我叫它“抽象”類)。<br>
          ?理論上來說,當(dāng)一個(gè)類成為祖宗類時(shí),必定意味著這個(gè)類包含了一些在子類中通用的行為,那么,從_Node暴露出來的方法來看,即所有的子類理論上都會(huì)有如下特征:<br>
          1. 可作為容器 (each_child, find_named_blocks)<br>
          2. generate<br>
          當(dāng)然了,理想總是豐滿的,現(xiàn)實(shí)也總有那么點(diǎn)兒不對勁,對于某些子孫,它們的特征看上去不是那么靠譜,比如_Text。<br>
          ?_Text這個(gè)類只用到了generate這個(gè)方法,用于將文字(Html, JS)經(jīng)過trim后添加到輸入流中,如果調(diào)用它的each_child or find_named_blocks,當(dāng)然你能這么做,但是沒有什么意義。<br>
          ?前面反復(fù)說到_Parse方法,它返回的結(jié)果是一個(gè)_ChunkList的實(shí)例,而_ChunkList繼承與_Node。這是一個(gè)體現(xiàn)了_Node容器特點(diǎn)的類,重寫了generate方法和each_child方法,而基本上就是依次調(diào)用容器內(nèi)所有元素的相關(guān)方法而已。<br>
          ?_Nodes眾多子子孫孫中比較奇葩的是_ExtendsBlock這個(gè)類,丫什么事情都沒做(That is true),看上去像是另外一個(gè)“抽象類”,但是居然會(huì)被_Parse初始化,用于處理Extends這個(gè)token(tornado術(shù)語)。我就納悶了,一旦這貨被generate,難道不會(huì)拋一個(gè)異常出來木?<br>
          ?真正有意思的是另外幾個(gè)方法,它們有共通的模式,用_ApplyBlock來舉例<br>
          ?在_ApplyBlock中,有趣的是generate方法<br>
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          def generate(self, writer): 
            method_name = "apply%d" % writer.apply_counter 
            writer.apply_counter += 1 
            writer.write_line("def %s():" % method_name, self.line) 
            with writer.indent(): 
              writer.write_line("_buffer = []", self.line) 
              writer.write_line("_append = _buffer.append", self.line) 
              self.body.generate(writer) 
              writer.write_line("return _utf8('').join(_buffer)", self.line) 
            writer.write_line("_append(%s(%s()))" % ( 
              self.method, method_name), self.line) 
          </pre>
          </p>
          <p>簡單來說,這個(gè)函數(shù)做了兩件事情:<br />
          定義了一個(gè)python文件全局函數(shù)叫做applyXXX():,其中的XXX是一個(gè)整形的,自增的值,返回值是一個(gè)utf8字符串。<br />
          執(zhí)行這個(gè)applyXXX函數(shù),將此函數(shù)的輸出再作為self.method這個(gè)函數(shù)的輸入。<br />
          所以,如果一個(gè)類似于這樣的模板<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          {%apply linkify%} {{address}} {%end%} 
          </pre>
          </p>
          <p>會(huì)得到一個(gè)類似于如下的輸出:<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          r = applyXXX() 
          r = linkify(r) 
          _append(r) 
          </pre>
          </p>
          <p>tornado的template機(jī)制,本質(zhì)上講,就是允許開發(fā)者已HTML + template marker的方式來編寫視圖模板,但是在背后,tornado會(huì)把這些視圖模板通過template的處理,變成可編譯的python代碼。<br />
           拿autumn-sea上面的代碼作為例子,比較容易理解:<br />
           View Template<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          <html> 
            <head> 
              <title>{{ title }}</title> 
            </head> 
            <body> 
              hello! {{ name }} 
            </body> 
          </html> </pre>
          </p>
          <p> 處理后<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          _buffer = [] 
          _buffer.append('<html>\\n<head>\\n<title>') 
           
          _tmp = title 
          if isinstance(_tmp, str): _buffer.append(_tmp) 
          elif isinstance(_tmp, unicode): _buffer.append(_tmp.encode('utf-8')) 
          else: _buffer.append(str(_tmp)) 
           
          _buffer.append('</title>\\n</head>\\n<body>\\n') 
          _buffer.append('hello! ') 
           
          _tmp = name 
          if isinstance(_tmp, str): _buffer.append(_tmp) 
          elif isinstance(_tmp, unicode): _buffer.append(_tmp.encode('utf-8')) 
          else: _buffer.append(str(_tmp)) 
           
          _buffer.append('\\n</body>\\n</html>\\n') 
          return ''.join(_buffer)\n" 
          </pre>
          </p>
          <p></p>
          <p><strong>實(shí)例剖析<br />
          </strong>tornado的模板基本都在template.py這個(gè)文件中,短短800多行代碼就實(shí)現(xiàn)了基本可用的模板,讓我們慢慢揭開她的面紗。<br />
          首先我們看看tornado是如何編譯模板的,下面是個(gè)簡單的模板<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          t = Template("""\ 
          {%if names%} 
            {% for name in names %} 
              {{name}} 
            {%end%} 
          {%else%} 
          no one 
          {%end%} 
          """) 
          </pre>
          </p>
          <p>tornado最后編譯代碼如下: <br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          def _tt_execute(): # <string>:0 
            _tt_buffer = [] # <string>:0 
            _tt_append = _tt_buffer.append # <string>:0 
            if names: # <string>:1 
              _tt_append('\n  ') # <string>:2 
              for name in names: # <string>:2 
                _tt_append('\n    ') # <string>:3 
                _tt_tmp = name # <string>:3 
                if isinstance(_tt_tmp, _tt_string_types): _tt_tmp = _tt_utf8(_tt_tmp) # <string>:3 
                else: _tt_tmp = _tt_utf8(str(_tt_tmp)) # <string>:3 
                _tt_tmp = _tt_utf8(xhtml_escape(_tt_tmp)) # <string>:3 
                _tt_append(_tt_tmp) # <string>:3 
                _tt_append('\n  ') # <string>:4 
                pass # <string>:2 
              _tt_append('\n') # <string>:5 
              pass # <string>:5 
            else: # <string>:5 
              _tt_append('\nno one\n') # <string>:7 
              pass # <string>:1 
            _tt_append('\n') # <string>:8 
            return _tt_utf8('').join(_tt_buffer) # <string>:0 
          </pre>
          </p>
          <p>是的,你沒看錯(cuò),tornado編譯就是將之翻譯成一個(gè)個(gè)代碼塊,最后通exec傳遞我們給的參數(shù)命名空間執(zhí)行_tt_execute函數(shù)。<br />
          在我們上面的模板中包含了4種預(yù)定義的NODE節(jié)點(diǎn),_ControlBlock,_Expression,_TEXT,每種Node節(jié)點(diǎn)都有自己的生成方式。<br />
          比如說_Expression表達(dá)式節(jié)點(diǎn),也就是我們模板中的{{name}},當(dāng)_parse解析時(shí)發(fā)現(xiàn)'{'后面還是'{'就認(rèn)為是表達(dá)式節(jié)點(diǎn),<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class _Expression(_Node): 
            def __init__(self, expression, line, raw=False): 
              self.expression = expression 
              self.line = line 
              self.raw = raw 
           
            def generate(self, writer): 
              writer.write_line("_tt_tmp = %s" % self.expression, self.line) 
              writer.write_line("if isinstance(_tt_tmp, _tt_string_types):" 
                       " _tt_tmp = _tt_utf8(_tt_tmp)", self.line) 
              writer.write_line("else: _tt_tmp = _tt_utf8(str(_tt_tmp))", self.line) 
              if not self.raw and writer.current_template.autoescape is not None: 
                # In python3 functions like xhtml_escape return unicode, 
                # so we have to convert to utf8 again. 
                writer.write_line("_tt_tmp = _tt_utf8(%s(_tt_tmp))" % 
                         writer.current_template.autoescape, self.line) 
              writer.write_line("_tt_append(_tt_tmp)", self.line) 
          </pre>
          </p>
          <p>最后生成時(shí)會(huì)調(diào)用節(jié)點(diǎn)的generate方法,self.expression就是上面的name,所以當(dāng)exec的時(shí)候就會(huì)把name的值append到內(nèi)部的列表中。<br />
          像if,for等都是控制節(jié)點(diǎn),他們的定義如下: <br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class _ControlBlock(_Node): 
            def __init__(self, statement, line, body=None): 
              self.statement = statement 
              self.line = line 
              self.body = body 
           
            def each_child(self): 
              return (self.body,) 
           
            def generate(self, writer): 
              writer.write_line("%s:" % self.statement, self.line) 
              with writer.indent(): 
                self.body.generate(writer) 
                # Just in case the body was empty 
                writer.write_line("pass", self.line) </pre>
          </p>
          <p><br />
          控制節(jié)點(diǎn)的generate方法有點(diǎn)意義,因?yàn)閕f,for等是下一行是需要縮進(jìn)的,所以調(diào)用了with writer.indent繼續(xù)縮進(jìn)控制,可以看下<br />
          _CodeWriter的indent方法。<br />
          節(jié)點(diǎn)中比較有意思的是_ExtendsBlock,這是實(shí)現(xiàn)目標(biāo)基礎(chǔ)的節(jié)點(diǎn),<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class _ExtendsBlock(_Node): 
            def __init__(self, name): 
              self.name = name 
          </pre>
          </p>
          <p>我們發(fā)現(xiàn)并沒有定義generate方法,那當(dāng)生成繼承節(jié)點(diǎn)時(shí)不是會(huì)報(bào)錯(cuò)嗎?讓我們看一段事例<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          loader = Loader('.') 
          t=Template("""\ 
          {% extends base.html %} 
          {% block login_name %}hello world! {{ name }}{% end %} 
          """,loader=loader) 
          </pre>
          </p>
          <p>當(dāng)前目錄下base.html如下:<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          <html>  
          <head>  
          <title>{{ title }}</title>  
          </head>  
          <body>  
          {% block login_name %}hello! {{ name }}{% end %}  
          </body>  
          </html> </pre>
          </p>
          <p> 我們可以看看解析后的節(jié)點(diǎn),<br />
          </p>
          <p><img src="/static/imghw/default1.png"  data-src="http://files.jb51.net/file_images/article/201607/2016711182740215.jpg?2016611182750"  class="lazy"  alt="2016711182740215.jpg (706×500)" /></p>
          <p>由于我們繼承了base.html,所以我們的應(yīng)該以base.html的模板生成,并使用新定義的block代替base.html中的block,<br />
          這是很正常的思路,tornado也的確是這么干的,只不過處理的并不是在_ExtendsBlock。<br />
          而實(shí)在Template的_generate_python中<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          def _generate_python(self, loader, compress_whitespace): 
             buffer = StringIO() 
             try: 
               # named_blocks maps from names to _NamedBlock objects 
               named_blocks = {} 
               ancestors = self._get_ancestors(loader) 
               ancestors.reverse() 
               for ancestor in ancestors: 
                 ancestor.find_named_blocks(loader, named_blocks) 
               writer = _CodeWriter(buffer, named_blocks, loader, ancestors[0].template, 
                         compress_whitespace) 
               ancestors[0].generate(writer) 
               return buffer.getvalue() 
             finally: 
               buffer.close() 
           
           def _get_ancestors(self, loader): 
             ancestors = [self.file] 
             for chunk in self.file.body.chunks: 
               if isinstance(chunk, _ExtendsBlock): 
                 if not loader: 
                   raise ParseError("{% extends %} block found, but no " 
                           "template loader") 
                 template = loader.load(chunk.name, self.name) 
                 ancestors.extend(template._get_ancestors(loader)) 
             return ancestors 
          </pre>
          </p>
          <p>_generate_python中調(diào)用_get_ancestors獲取當(dāng)前模板的父模板,我們看到如果當(dāng)前模板的_FILE節(jié)點(diǎn)中有_ExtendsBlock就代表有父模板并通過loader.load加載父模板,此時(shí)父模板已經(jīng)是解析過的_FILE節(jié)點(diǎn)了。所以,在上面的模板中,ancestors是[當(dāng)前模板_FILE節(jié)點(diǎn),父模板_FILE節(jié)點(diǎn)],ancestors.reverse()后其實(shí)ancestors[0]就是父模板,我們看到最后是通過ancestors[0].generate(writer)來生成代碼的。那當(dāng)前模板是如何替換父模板的block內(nèi)容呢?<br />
          看上圖,block login_name通過解析為_NamedBlock,在_generate_python中通過調(diào)用ancestor.find_named_blocks來替換<br />
          父模板的_NamedBlock的。<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          for ancestor in ancestors:
              ancestor.find_named_blocks(loader, named_blocks)
          ancestor其實(shí)就是_FILE節(jié)點(diǎn),find_named_blocks將遍歷_FILE節(jié)點(diǎn)中所有節(jié)點(diǎn)并調(diào)用find_named_blocks
           
          class _NamedBlock(_Node): 
            def find_named_blocks(self, loader, named_blocks): 
              named_blocks[self.name] = self 
              _Node.find_named_blocks(self, loader, named_blocks) 
          </pre>
          </p>
          <p>其它節(jié)點(diǎn)find_named_blocks都沒有做什么事,_NamedBlock通過named_blocks[self.name] = self替換為當(dāng)前模板的_NamedBlock,因?yàn)閍ncestors父模板在前,當(dāng)前模板在后,所以最后使用的是當(dāng)前模板的_NamedBlock。<br />
          生成代碼后generate將在給定的命名空間中exec代碼<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          def generate(self, **kwargs): 
            """Generate this template with the given arguments.""" 
            namespace = { 
              "escape": escape.xhtml_escape, 
              "xhtml_escape": escape.xhtml_escape, 
              "url_escape": escape.url_escape, 
              "json_encode": escape.json_encode, 
              "squeeze": escape.squeeze, 
              "linkify": escape.linkify, 
              "datetime": datetime, 
              "_tt_utf8": escape.utf8, # for internal use 
              "_tt_string_types": (unicode_type, bytes_type), 
              # __name__ and __loader__ allow the traceback mechanism to find 
              # the generated source code. 
              "__name__": self.name.replace('.', '_'), 
              "__loader__": ObjectDict(get_source=lambda name: self.code), 
            } 
            namespace.update(self.namespace) 
            namespace.update(kwargs) 
            exec_in(self.compiled, namespace) 
            execute = namespace["_tt_execute"] 
            # Clear the traceback module's cache of source data now that 
            # we've generated a new template (mainly for this module's 
            # unittests, where different tests reuse the same name). 
            linecache.clearcache() 
            return execute() 
          </pre>
          </p>
          <p>所以在模板中可以使用datetime等,都是通過在這里注入到模板中的,當(dāng)然還有其它的是通過<br />
          web.py 中g(shù)et_template_namespace注入的 <br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
           def get_template_namespace(self): 
             """Returns a dictionary to be used as the default template namespace. 
           
             May be overridden by subclasses to add or modify values. 
           
             The results of this method will be combined with additional 
             defaults in the `tornado.template` module and keyword arguments 
             to `render` or `render_string`. 
             """ 
             namespace = dict( 
               handler=self, 
               request=self.request, 
               current_user=self.current_user, 
               locale=self.locale, 
               _=self.locale.translate, 
               static_url=self.static_url, 
               xsrf_form_html=self.xsrf_form_html, 
               reverse_url=self.reverse_url 
             ) 
             namespace.update(self.ui) 
             return namespace 
          </pre>
          </p>
          <p>我們再來看看tornado的模板是如何對UI模塊的支持的。<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          {% for entry in entries %} 
           {% module Entry(entry) %} 
          {% end %} 
          </pre>
          </p>
          <p>在使用module時(shí)將會(huì)生成_Module節(jié)點(diǎn) <br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class _Module(_Expression): 
            def __init__(self, expression, line): 
              super(_Module, self).__init__("_tt_modules." + expression, line, 
                             raw=True) 
          </pre>
          </p>
          <p>我們看到其實(shí)_Module節(jié)點(diǎn)是繼承自_Expression節(jié)點(diǎn),所以最后執(zhí)行的是_tt_modules.Entry(entry)<br />
          _tt_modules定義在web.py的RequestHandler中<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          self.ui["_tt_modules"] = _UIModuleNamespace(self,application.ui_modules)
          </pre>
          </p>
          <p>并通過上文的get_template_namespace中注入到模板中。<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class _UIModuleNamespace(object): 
            """Lazy namespace which creates UIModule proxies bound to a handler.""" 
            def __init__(self, handler, ui_modules): 
              self.handler = handler 
              self.ui_modules = ui_modules 
           
            def __getitem__(self, key): 
              return self.handler._ui_module(key, self.ui_modules[key]) 
           
            def __getattr__(self, key): 
              try: 
                return self[key] 
              except KeyError as e: 
                raise AttributeError(str(e)) 
          </pre>
          </p>
          <p>所以當(dāng)執(zhí)行_tt_modules.Entry(entry)時(shí)先訪問_UIModuleNamespace的__getattr__,后訪問__getitem__,最后調(diào)用<br />
          handler._ui_module(key, self.ui_modules[key]),<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          def _ui_module(self, name, module): 
            def render(*args, **kwargs): 
              if not hasattr(self, "_active_modules"): 
                self._active_modules = {} 
              if name not in self._active_modules: 
                self._active_modules[name] = module(self) 
              rendered = self._active_modules[name].render(*args, **kwargs) 
              return rendered 
            return render 
          </pre>
          </p>
          <p>_tt_modules.Entry(entry)中entry將會(huì)傳給_ui_module內(nèi)部的render,也就是args=entry<br />
          self._active_modules[name] = module(self)此時(shí)就是實(shí)例化后的UIModule,調(diào)用render獲取渲染后的內(nèi)容<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class Entry(tornado.web.UIModule): 
            def render(self, entry, show_comments=False): 
              return self.render_string( 
                "module-entry.html", entry=entry, show_comments=show_comments) </pre>
          </p>
          <p>當(dāng)然如果你覺得這么做費(fèi)事,也可以使用tornado自帶的TemplateModule,它繼承自UIModule,<br />
          你可以這么用<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          {% module Template("module-entry.html", show_comments=True) %} 
          </pre>
          </p>
          <p>在module_entry.html中可以通過set_resources引用需要的靜態(tài)文件<br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          {{ set_resources(embedded_css=".entry { margin-bottom: 1em; }") }} 
          </pre>
          </p>
          <p>這里需要注意的是:只能在Template引用的html文件中使用set_resources函數(shù),因?yàn)閟et_resources是TemplateModule.render的內(nèi)部函數(shù) <br />
          </p>
          <div   id="377j5v51b"   class="jb51code">
          <pre class='brush:php;toolbar:false;'>
          class TemplateModule(UIModule): 
            """UIModule that simply renders the given template. 
           
            {% module Template("foo.html") %} is similar to {% include "foo.html" %}, 
            but the module version gets its own namespace (with kwargs passed to 
            Template()) instead of inheriting the outer template's namespace. 
           
            Templates rendered through this module also get access to UIModule's 
            automatic javascript/css features. Simply call set_resources 
            inside the template and give it keyword arguments corresponding to 
            the methods on UIModule: {{ set_resources(js_files=static_url("my.js")) }} 
            Note that these resources are output once per template file, not once 
            per instantiation of the template, so they must not depend on 
            any arguments to the template. 
            """ 
            def __init__(self, handler): 
              super(TemplateModule, self).__init__(handler) 
              # keep resources in both a list and a dict to preserve order 
              self._resource_list = [] 
              self._resource_dict = {} 
           
            def render(self, path, **kwargs): 
              def set_resources(**kwargs): 
                if path not in self._resource_dict: 
                  self._resource_list.append(kwargs) 
                  self._resource_dict[path] = kwargs 
                else: 
                  if self._resource_dict[path] != kwargs: 
                    raise ValueError("set_resources called with different " 
                             "resources for the same template") 
                return "" 
              return self.render_string(path, set_resources=set_resources, 
                           **kwargs) </pre>
          
          <p></p>
          
          </div>
          
          
          						</div>
          					</div>
          					<div   id="377j5v51b"   class="wzconShengming_sp">
          						<div   id="377j5v51b"   class="bzsmdiv_sp">Erkl?rung dieser Website</div>
          						<div>Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn</div>
          					</div>
          				</div>
          
          				<ins class="adsbygoogle"
               style="display:block"
               data-ad-format="autorelaxed"
               data-ad-client="ca-pub-5902227090019525"
               data-ad-slot="2507867629"></ins>
          
          
          
          				<div   id="377j5v51b"   class="AI_ToolDetails_main4sR">
          
          
          				<ins class="adsbygoogle"
                  style="display:block"
                  data-ad-client="ca-pub-5902227090019525"
                  data-ad-slot="3653428331"
                  data-ad-format="auto"
                  data-full-width-responsive="true"></ins>
              
          
          
          					<!-- <div   id="377j5v51b"   class="phpgenera_Details_mainR4">
          						<div   id="377j5v51b"   class="phpmain1_4R_readrank">
          							<div   id="377j5v51b"   class="phpmain1_4R_readrank_top">
          								<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									src="/static/imghw/hotarticle2.png" alt="" />
          								<h2>Hei?er Artikel</h2>
          							</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottom">
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796832397.html" title="Gras Wonder Build Guide | Uma Musume hübsches Derby" class="phpgenera_Details_mainR4_bottom_title">Gras Wonder Build Guide | Uma Musume hübsches Derby</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>1 Monate vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796833110.html" title="<??>: 99 N?chte im Wald - alle Abzeichen und wie man sie freischalt" class="phpgenera_Details_mainR4_bottom_title"><??>: 99 N?chte im Wald - alle Abzeichen und wie man sie freischalt</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>1 Monate vor</span>
          										<span>By DDD</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796836699.html" title="Rimworld Odyssey -Temperaturführer für Schiffe und Gravtech" class="phpgenera_Details_mainR4_bottom_title">Rimworld Odyssey -Temperaturführer für Schiffe und Gravtech</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>3 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796834553.html" title="Mejiro Ryan Build Guide | Uma Musume hübsches Derby" class="phpgenera_Details_mainR4_bottom_title">Mejiro Ryan Build Guide | Uma Musume hübsches Derby</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>4 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796836084.html" title="Rimworld odyssey wie man fischt" class="phpgenera_Details_mainR4_bottom_title">Rimworld odyssey wie man fischt</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>3 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          														</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR3_more">
          								<a href="http://m.miracleart.cn/de/article.html">Mehr anzeigen</a>
          							</div>
          						</div>
          					</div> -->
          
          
          											<div   id="377j5v51b"   class="phpgenera_Details_mainR3">
          							<div   id="377j5v51b"   class="phpmain1_4R_readrank">
          								<div   id="377j5v51b"   class="phpmain1_4R_readrank_top">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/hottools2.png" alt="" />
          									<h2>Hei?e KI -Werkzeuge</h2>
          								</div>
          								<div   id="377j5v51b"   class="phpgenera_Details_mainR3_bottom">
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/ai/undress-ai-tool" title="Undress AI Tool" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/ai_manual/001/246/273/173410641626608.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Undress AI Tool" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/ai/undress-ai-tool" title="Undress AI Tool" class="phpmain_tab2_mids_title">
          													<h3>Undress AI Tool</h3>
          												</a>
          												<p>Ausziehbilder kostenlos</p>
          											</div>
          										</div>
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/ai/undresserai-undress" title="Undresser.AI Undress" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411540686492.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Undresser.AI Undress" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/ai/undresserai-undress" title="Undresser.AI Undress" class="phpmain_tab2_mids_title">
          													<h3>Undresser.AI Undress</h3>
          												</a>
          												<p>KI-gestützte App zum Erstellen realistischer Aktfotos</p>
          											</div>
          										</div>
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/ai/ai-clothes-remover" title="AI Clothes Remover" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411552797167.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="AI Clothes Remover" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/ai/ai-clothes-remover" title="AI Clothes Remover" class="phpmain_tab2_mids_title">
          													<h3>AI Clothes Remover</h3>
          												</a>
          												<p>Online-KI-Tool zum Entfernen von Kleidung aus Fotos.</p>
          											</div>
          										</div>
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/ai/clothoffio" title="Clothoff.io" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411529149311.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Clothoff.io" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/ai/clothoffio" title="Clothoff.io" class="phpmain_tab2_mids_title">
          													<h3>Clothoff.io</h3>
          												</a>
          												<p>KI-Kleiderentferner</p>
          											</div>
          										</div>
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/ai/video-swap" title="Video Face Swap" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/ai_manual/001/246/273/173414504068133.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Video Face Swap" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/ai/video-swap" title="Video Face Swap" class="phpmain_tab2_mids_title">
          													<h3>Video Face Swap</h3>
          												</a>
          												<p>Tauschen Sie Gesichter in jedem Video mühelos mit unserem v?llig kostenlosen KI-Gesichtstausch-Tool aus!</p>
          											</div>
          										</div>
          																</div>
          								<div   id="377j5v51b"   class="phpgenera_Details_mainR3_more">
          									<a href="http://m.miracleart.cn/de/ai">Mehr anzeigen</a>
          								</div>
          							</div>
          						</div>
          					
          
          
          					<div   id="377j5v51b"   class="phpgenera_Details_mainR4">
          						<div   id="377j5v51b"   class="phpmain1_4R_readrank">
          							<div   id="377j5v51b"   class="phpmain1_4R_readrank_top">
          								<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									src="/static/imghw/hotarticle2.png" alt="" />
          								<h2>Hei?er Artikel</h2>
          							</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottom">
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796832397.html" title="Gras Wonder Build Guide | Uma Musume hübsches Derby" class="phpgenera_Details_mainR4_bottom_title">Gras Wonder Build Guide | Uma Musume hübsches Derby</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>1 Monate vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796833110.html" title="<??>: 99 N?chte im Wald - alle Abzeichen und wie man sie freischalt" class="phpgenera_Details_mainR4_bottom_title"><??>: 99 N?chte im Wald - alle Abzeichen und wie man sie freischalt</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>1 Monate vor</span>
          										<span>By DDD</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796836699.html" title="Rimworld Odyssey -Temperaturführer für Schiffe und Gravtech" class="phpgenera_Details_mainR4_bottom_title">Rimworld Odyssey -Temperaturführer für Schiffe und Gravtech</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>3 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796834553.html" title="Mejiro Ryan Build Guide | Uma Musume hübsches Derby" class="phpgenera_Details_mainR4_bottom_title">Mejiro Ryan Build Guide | Uma Musume hübsches Derby</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>4 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/1796836084.html" title="Rimworld odyssey wie man fischt" class="phpgenera_Details_mainR4_bottom_title">Rimworld odyssey wie man fischt</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<span>3 Wochen vor</span>
          										<span>By Jack chen</span>
          									</div>
          								</div>
          														</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR3_more">
          								<a href="http://m.miracleart.cn/de/article.html">Mehr anzeigen</a>
          							</div>
          						</div>
          					</div>
          
          
          											<div   id="377j5v51b"   class="phpgenera_Details_mainR3">
          							<div   id="377j5v51b"   class="phpmain1_4R_readrank">
          								<div   id="377j5v51b"   class="phpmain1_4R_readrank_top">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/hottools2.png" alt="" />
          									<h2>Hei?e Werkzeuge</h2>
          								</div>
          								<div   id="377j5v51b"   class="phpgenera_Details_mainR3_bottom">
          																		<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/toolset/development-tools/92" title="Notepad++7.3.1" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/manual/000/000/001/58ab96f0f39f7357.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Notepad++7.3.1" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/toolset/development-tools/92" title="Notepad++7.3.1" class="phpmain_tab2_mids_title">
          													<h3>Notepad++7.3.1</h3>
          												</a>
          												<p>Einfach zu bedienender und kostenloser Code-Editor</p>
          											</div>
          										</div>
          																			<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/toolset/development-tools/93" title="SublimeText3 chinesische Version" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/manual/000/000/001/58ab97a3baad9677.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="SublimeText3 chinesische Version" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/toolset/development-tools/93" title="SublimeText3 chinesische Version" class="phpmain_tab2_mids_title">
          													<h3>SublimeText3 chinesische Version</h3>
          												</a>
          												<p>Chinesische Version, sehr einfach zu bedienen</p>
          											</div>
          										</div>
          																			<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/toolset/development-tools/121" title="Senden Sie Studio 13.0.1" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/manual/000/000/001/58ab97ecd1ab2670.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Senden Sie Studio 13.0.1" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/toolset/development-tools/121" title="Senden Sie Studio 13.0.1" class="phpmain_tab2_mids_title">
          													<h3>Senden Sie Studio 13.0.1</h3>
          												</a>
          												<p>Leistungsstarke integrierte PHP-Entwicklungsumgebung</p>
          											</div>
          										</div>
          																			<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/toolset/development-tools/469" title="Dreamweaver CS6" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/manual/000/000/001/58d0e0fc74683535.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Dreamweaver CS6" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/toolset/development-tools/469" title="Dreamweaver CS6" class="phpmain_tab2_mids_title">
          													<h3>Dreamweaver CS6</h3>
          												</a>
          												<p>Visuelle Webentwicklungstools</p>
          											</div>
          										</div>
          																			<div   id="377j5v51b"   class="phpmain_tab2_mids_top">
          											<a href="http://m.miracleart.cn/de/toolset/development-tools/500" title="SublimeText3 Mac-Version" class="phpmain_tab2_mids_top_img">
          												<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          													class="lazy"  data-src="https://img.php.cn/upload/manual/000/000/001/58d34035e2757995.png?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="SublimeText3 Mac-Version" />
          											</a>
          											<div   id="377j5v51b"   class="phpmain_tab2_mids_info">
          												<a href="http://m.miracleart.cn/de/toolset/development-tools/500" title="SublimeText3 Mac-Version" class="phpmain_tab2_mids_title">
          													<h3>SublimeText3 Mac-Version</h3>
          												</a>
          												<p>Codebearbeitungssoftware auf Gottesniveau (SublimeText3)</p>
          											</div>
          										</div>
          																	</div>
          								<div   id="377j5v51b"   class="phpgenera_Details_mainR3_more">
          									<a href="http://m.miracleart.cn/de/ai">Mehr anzeigen</a>
          								</div>
          							</div>
          						</div>
          										
          
          					
          					<div   id="377j5v51b"   class="phpgenera_Details_mainR4">
          						<div   id="377j5v51b"   class="phpmain1_4R_readrank">
          							<div   id="377j5v51b"   class="phpmain1_4R_readrank_top">
          								<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          									src="/static/imghw/hotarticle2.png" alt="" />
          								<h2>Hei?e Themen</h2>
          							</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottom">
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/laravel-tutori" title="Laravel-Tutorial" class="phpgenera_Details_mainR4_bottom_title">Laravel-Tutorial</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_infos">
          											<img src="/static/imghw/eyess.png" alt="" />
          											<span>1601</span>
          										</div>
          										<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_infos">
          											<img src="/static/imghw/tiezi.png" alt="" />
          											<span>29</span>
          										</div>
          									</div>
          								</div>
          															<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms">
          									<a href="http://m.miracleart.cn/de/faq/php-tutorial" title="PHP-Tutorial" class="phpgenera_Details_mainR4_bottom_title">PHP-Tutorial</a>
          									<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_info">
          										<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_infos">
          											<img src="/static/imghw/eyess.png" alt="" />
          											<span>1502</span>
          										</div>
          										<div   id="377j5v51b"   class="phpgenera_Details_mainR4_bottoms_infos">
          											<img src="/static/imghw/tiezi.png" alt="" />
          											<span>276</span>
          										</div>
          									</div>
          								</div>
          														</div>
          							<div   id="377j5v51b"   class="phpgenera_Details_mainR3_more">
          								<a href="http://m.miracleart.cn/de/faq/zt">Mehr anzeigen</a>
          							</div>
          						</div>
          					</div>
          				</div>
          			</div>
          							<div   id="377j5v51b"   class="Article_Details_main2">
          					<div   id="377j5v51b"   class="phpgenera_Details_mainL4">
          						<div   id="377j5v51b"   class="phpmain1_2_top">
          							<a href="javascript:void(0);" class="phpmain1_2_top_title">Related knowledge<img
          									src="/static/imghw/index2_title2.png" alt="" /></a>
          						</div>
          						<div   id="377j5v51b"   class="phpgenera_Details_mainL4_info">
          
          													<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796847651.html" title="Python Seeborn JointPlot Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175348871135130.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python Seeborn JointPlot Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796847651.html" title="Python Seeborn JointPlot Beispiel" class="phphistorical_Version2_mids_title">Python Seeborn JointPlot Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 26, 2025 am	 08:11 AM</span>
          								<p class="Articlelist_txts_p">Verwenden Sie die Jointplot von Seeborn, um die Beziehung und Verteilung zwischen zwei Variablen schnell zu visualisieren. 2. Das grundlegende Streudiagramm wird durch sns.jointplot (data = tips, x = "total_bill", y = "tip", sort = "scatter") implementiert, das Zentrum ist ein Streudiagramm und das Histogramm wird auf der oberen und unteren und rechten Seite angezeigt. 3. Fügen Sie Regressionslinien und Dichteinformationen zu einer Art "Reg" hinzu und kombinieren Sie Marginal_KWS, um den Edge -Plot -Stil festzulegen. 4. Wenn das Datenvolumen gro? ist, wird empfohlen, "Hex" zu verwenden,</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796847620.html" title="Python -Liste zum String Conversion Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175348803380357.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python -Liste zum String Conversion Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796847620.html" title="Python -Liste zum String Conversion Beispiel" class="phphistorical_Version2_mids_title">Python -Liste zum String Conversion Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 26, 2025 am	 08:00 AM</span>
          								<p class="Articlelist_txts_p">String -Listen k?nnen mit der join () -Methode wie '' .Join (Words) zusammengeführt werden, um "helloWorldfrompython" zu erhalten; 2. Die Zahlenlisten müssen vor dem Beitritt in Zeichenfolgen mit Karte (STR, Zahlen) oder [STR (x) ForxInnumbers] konvertiert werden. 3. Jede Typliste kann direkt in Zeichenfolgen mit Klammern und Zitaten umgewandelt werden, die zum Debuggen geeignet sind. 4. Benutzerdefinierte Formate k?nnen durch Generatorausdrücke in Kombination mit Join () implementiert werden, wie z.</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796851468.html" title="Python verbinden sich mit SQL Server PyoDBC -Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175381521174852.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python verbinden sich mit SQL Server PyoDBC -Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796851468.html" title="Python verbinden sich mit SQL Server PyoDBC -Beispiel" class="phphistorical_Version2_mids_title">Python verbinden sich mit SQL Server PyoDBC -Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 30, 2025 am	 02:53 AM</span>
          								<p class="Articlelist_txts_p">Installieren Sie PYODBC: Verwenden Sie den Befehl pipinstallpyoDBC, um die Bibliothek zu installieren. 2. SQLServer verbinden: Verwenden Sie die Verbindungszeichenfolge, die Treiber, Server, Datenbank, UID/PWD oder Trusted_Connection über die Methode Pyodbc.Connect () und die SQL -Authentifizierung bzw. der Windows -Authentifizierung unterstützen; 3. überprüfen Sie den installierten Treiber: Führen Sie Pyodbc.Drivers () aus und filtern Sie den Treibernamen mit 'SQLServer', um sicherzustellen, dass der richtige Treiberame wie 'ODBCDRIVER17 für SQLServer' verwendet wird. 4. Schlüsselparameter der Verbindungszeichenfolge</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796848426.html" title="Python Pandas Schmelze Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175355571120355.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python Pandas Schmelze Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796848426.html" title="Python Pandas Schmelze Beispiel" class="phphistorical_Version2_mids_title">Python Pandas Schmelze Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 27, 2025 am	 02:48 AM</span>
          								<p class="Articlelist_txts_p">Pandas.Melt () wird verwendet, um weite Formatdaten in ein langes Format umzuwandeln. Die Antwort besteht darin, neue Spaltennamen zu definieren, indem id_vars angegeben wird, die Identifikationsspalte beibehalten. 4.Value_name = 'Score' legt den neuen Spaltennamen des ursprünglichen Wertes fest und generiert schlie?lich drei Spalten, einschlie?lich Name, Betreff und Punktzahl.</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796849397.html" title="Optimierung von Python für Speichervorg?nge" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/253/068/175364417192026.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Optimierung von Python für Speichervorg?nge" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796849397.html" title="Optimierung von Python für Speichervorg?nge" class="phphistorical_Version2_mids_title">Optimierung von Python für Speichervorg?nge</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 28, 2025 am	 03:22 AM</span>
          								<p class="Articlelist_txts_p">PythoncanbeoptimizedFormemory-BoundoperationsByreducingoverheadThroughGeneratoren, effiziente Datastrukturen und ManagingObjectLifetimes.First, UseGeneratorsinSteadofListStoprocesslargedatasetasetasematatime, Vermeidung von loloadingeNthertomemory.Secondatasetasetematatime, Choos</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796848434.html" title="Python Django bildet Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175355585018478.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python Django bildet Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796848434.html" title="Python Django bildet Beispiel" class="phphistorical_Version2_mids_title">Python Django bildet Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 27, 2025 am	 02:50 AM</span>
          								<p class="Articlelist_txts_p">Definieren Sie zun?chst ein ContactForm -Formular mit Namen, Mailbox und Nachrichtenfeldern. 2. In der Ansicht wird die Einreichung von Formular durch die Beurteilung der Postanfrage bearbeitet, und nach der überprüfung wird Cleaned_data erhalten und die Antwort wird zurückgegeben, sonst wird das leere Formular gerendert. 3. In der Vorlage verwenden Sie {{{form.as_p}}, um das Feld zu rendern und {%csrf_token%} hinzuzufügen, um CSRF -Angriffe zu verhindern; 4. Konfigurieren Sie die URL -Routing auf Punkt / Kontakt / an die Ansicht contact_view; Verwenden Sie Modelform, um das Modell direkt zu verknüpfen, um die Datenspeicherung zu erreichen. DjangoForms implementiert eine integrierte Verarbeitung von Datenüberprüfung, HTML -Rendering und Fehleraufforderungen, die für die schnelle Entwicklung sicherer Formfunktionen geeignet sind.</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796851967.html" title="Was ist statistische Arbitrage in Kryptow?hrungen? Wie funktioniert statistische Arbitrage?" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/246/273/175385833690447.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Was ist statistische Arbitrage in Kryptow?hrungen? Wie funktioniert statistische Arbitrage?" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796851967.html" title="Was ist statistische Arbitrage in Kryptow?hrungen? Wie funktioniert statistische Arbitrage?" class="phphistorical_Version2_mids_title">Was ist statistische Arbitrage in Kryptow?hrungen? Wie funktioniert statistische Arbitrage?</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 30, 2025 pm	 09:12 PM</span>
          								<p class="Articlelist_txts_p">Die Einführung in statistische Arbitrage Statistical Arbitrage ist eine Handelsmethode, die auf der Grundlage mathematischer Modelle Preisfehlanpassungen auf dem Finanzmarkt erfasst. Die Kernphilosophie beruht auf der mittleren Regression, dh, dass die Verm?genspreise kurzfristig von langfristigen Trends abweichen, aber schlie?lich zu ihrem historischen Durchschnitt zurückkehren. H?ndler verwenden statistische Methoden, um die Korrelation zwischen Verm?genswerten zu analysieren und nach Portfolios zu suchen, die normalerweise synchron ver?ndern. Wenn das Preisverh?ltnis dieser Verm?genswerte ungew?hnlich abgewichen ist, ergeben sich Arbitrage -M?glichkeiten. Auf dem Kryptow?hrungsmarkt ist die statistische Arbitrage besonders weit verbreitet, haupts?chlich aufgrund der Ineffizienz und drastischen Marktschwankungen des Marktes selbst. Im Gegensatz zu den traditionellen Finanzm?rkten arbeiten Kryptow?hrungen rund um die Uhr und ihre Preise sind ?u?erst anf?llig für Verst??e gegen Nachrichten, Social -Media -Stimmung und technologische Upgrades. Diese konstante Preisschwankung schafft h?ufig Preisgestaltung und liefert Arbitrageure mit</p>
          							</div>
          														<div   id="377j5v51b"   class="phphistorical_Version2_mids">
          								<a href="http://m.miracleart.cn/de/faq/1796850166.html" title="Python Iter und n?chstes Beispiel" class="phphistorical_Version2_mids_img">
          									<img onerror="this.onerror=''; this.src='/static/imghw/default1.png'"
          										src="/static/imghw/default1.png" class="lazy"  data-src="https://img.php.cn/upload/article/001/431/639/175372683278308.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Python Iter und n?chstes Beispiel" />
          								</a>
          								<a href="http://m.miracleart.cn/de/faq/1796850166.html" title="Python Iter und n?chstes Beispiel" class="phphistorical_Version2_mids_title">Python Iter und n?chstes Beispiel</a>
          								<span id="377j5v51b"    class="Articlelist_txts_time">Jul 29, 2025 am	 02:20 AM</span>
          								<p class="Articlelist_txts_p">Iter () wird verwendet, um das Iteratorobjekt zu erhalten, und als n?chstes () wird das n?chste Element erhalten. 1. Verwenden Sie Iterator (), um iterable Objekte wie Listen in Iteratoren umzuwandeln. 2. Rufen Sie als n?chstes an () an, um Elemente nacheinander zu erhalten, und ausl?sen Sie die Ausnahme der Stopperation, wenn die Elemente ersch?pft sind. 3. Verwenden Sie als n?chstes (Iterator, Standard), um Ausnahmen zu vermeiden. 4. Benutzerdefinierte Iteratoren müssen die Methoden __iter __ () und __Next __ () implementieren, um die Iterationslogik zu kontrollieren; Die Verwendung von Standardwerten ist ein h?ufiger Weg zum sicheren Traversal, und der gesamte Mechanismus ist pr?gnant und praktisch.</p>
          							</div>
          													</div>
          
          													<a href="http://m.miracleart.cn/de/be/" class="phpgenera_Details_mainL4_botton">
          								<span>See all articles</span>
          								<img src="/static/imghw/down_right.png" alt="" />
          							</a>
          											</div>
          				</div>
          					</div>
          	</main>
          	<footer>
              <div   id="377j5v51b"   class="footer">
                  <div   id="377j5v51b"   class="footertop">
                      <img src="/static/imghw/logo.png" alt="">
                      <p>Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!</p>
                  </div>
                  <div   id="377j5v51b"   class="footermid">
                      <a href="http://m.miracleart.cn/de/about/us.html">über uns</a>
                      <a href="http://m.miracleart.cn/de/about/disclaimer.html">Haftungsausschluss</a>
                      <a href="http://m.miracleart.cn/de/update/article_0_1.html">Sitemap</a>
                  </div>
                  <div   id="377j5v51b"   class="footerbottom">
                      <p>
                          ? php.cn All rights reserved
                      </p>
                  </div>
              </div>
          </footer>
          
          <input type="hidden" id="verifycode" value="/captcha.html">
          
          
          
          
          		<link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css?2' type='text/css' media='all' />
          	
          	
          	
          	
          	
          
          	
          	
          
          
          
          
          
          
          <footer>
          <div class="friendship-link">
          <p>感谢您访问我们的网站,您可能还对以下资源感兴趣:</p>
          <a href="http://m.miracleart.cn/" title="国产av日韩一区二区三区精品">国产av日韩一区二区三区精品</a>
          
          <div class="friend-links">
          
          
          </div>
          </div>
          
          </footer>
          
          
          <script>
          (function(){
              var bp = document.createElement('script');
              var curProtocol = window.location.protocol.split(':')[0];
              if (curProtocol === 'https') {
                  bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
              }
              else {
                  bp.src = 'http://push.zhanzhang.baidu.com/push.js';
              }
              var s = document.getElementsByTagName("script")[0];
              s.parentNode.insertBefore(bp, s);
          })();
          </script>
          </body><div id="ryg5d" class="pl_css_ganrao" style="display: none;"><rp id="ryg5d"><acronym id="ryg5d"></acronym></rp><tr id="ryg5d"></tr><strike id="ryg5d"><video id="ryg5d"><pre id="ryg5d"></pre></video></strike><cite id="ryg5d"><ruby id="ryg5d"><dl id="ryg5d"><button id="ryg5d"></button></dl></ruby></cite><video id="ryg5d"><pre id="ryg5d"></pre></video><ruby id="ryg5d"></ruby><pre id="ryg5d"><menu id="ryg5d"></menu></pre><pre id="ryg5d"></pre><thead id="ryg5d"><i id="ryg5d"></i></thead><tbody id="ryg5d"><strike id="ryg5d"><var id="ryg5d"></var></strike></tbody><th id="ryg5d"></th><optgroup id="ryg5d"><legend id="ryg5d"><th id="ryg5d"><tbody id="ryg5d"></tbody></th></legend></optgroup><tfoot id="ryg5d"></tfoot><address id="ryg5d"></address><p id="ryg5d"></p><center id="ryg5d"><label id="ryg5d"><sub id="ryg5d"><object id="ryg5d"></object></sub></label></center><strong id="ryg5d"><em id="ryg5d"></em></strong><optgroup id="ryg5d"><meter id="ryg5d"></meter></optgroup><font id="ryg5d"><menu id="ryg5d"><dd id="ryg5d"><strong id="ryg5d"></strong></dd></menu></font><input id="ryg5d"><em id="ryg5d"></em></input><ol id="ryg5d"><small id="ryg5d"><rt id="ryg5d"><small id="ryg5d"></small></rt></small></ol><bdo id="ryg5d"><meter id="ryg5d"><var id="ryg5d"></var></meter></bdo><option id="ryg5d"><acronym id="ryg5d"><tt id="ryg5d"><center id="ryg5d"></center></tt></acronym></option><track id="ryg5d"></track><big id="ryg5d"></big><menu id="ryg5d"><font id="ryg5d"></font></menu><label id="ryg5d"></label><acronym id="ryg5d"></acronym><i id="ryg5d"></i><em id="ryg5d"></em><dl id="ryg5d"><em id="ryg5d"><i id="ryg5d"></i></em></dl><listing id="ryg5d"></listing><thead id="ryg5d"></thead><strong id="ryg5d"><progress id="ryg5d"></progress></strong><mark id="ryg5d"><label id="ryg5d"><sub id="ryg5d"><optgroup id="ryg5d"></optgroup></sub></label></mark><mark id="ryg5d"></mark><legend id="ryg5d"></legend><button id="ryg5d"><input id="ryg5d"><dfn id="ryg5d"></dfn></input></button><strong id="ryg5d"><menuitem id="ryg5d"></menuitem></strong><pre id="ryg5d"></pre><dfn id="ryg5d"><div id="ryg5d"></div></dfn><strike id="ryg5d"><acronym id="ryg5d"><sup id="ryg5d"><b id="ryg5d"></b></sup></acronym></strike><progress id="ryg5d"></progress><strike id="ryg5d"><video id="ryg5d"><strike id="ryg5d"><th id="ryg5d"></th></strike></video></strike><samp id="ryg5d"><p id="ryg5d"><mark id="ryg5d"><strong id="ryg5d"></strong></mark></p></samp><progress id="ryg5d"></progress><em id="ryg5d"></em><progress id="ryg5d"></progress><style id="ryg5d"></style><p id="ryg5d"></p></div>
          
          </html>