python---redis緩存頁面前戲之剖析render源碼
阿新 • • 發佈:2018-03-20
http addition war ads include 參數 sca calling face
1.初始代碼:
def get(self, *args, **kwargs): import time tm = time.time() self.render(‘home/index.html‘, time=tm)
2.代碼追蹤render:
# 第一次執行get方法時,通過render方法已經生成了數據,具體存在地方,參見源碼 def render(self, template_name, **kwargs): """Renders the template with the given arguments as the response.""" if self._finished: raise RuntimeError("Cannot render() after finish()") html = self.render_string(template_name, **kwargs) # Insert the additional JS and CSS added by the modules on the page js_embed = [] js_files = [] css_embed = [] css_files= [] html_heads = [] html_bodies = [] for module in getattr(self, "_active_modules", {}).values(): embed_part = module.embedded_javascript() if embed_part: js_embed.append(utf8(embed_part)) file_part = module.javascript_files()if file_part: if isinstance(file_part, (unicode_type, bytes)): js_files.append(file_part) else: js_files.extend(file_part) embed_part = module.embedded_css() if embed_part: css_embed.append(utf8(embed_part)) file_part = module.css_files() if file_part: if isinstance(file_part, (unicode_type, bytes)): css_files.append(file_part) else: css_files.extend(file_part) head_part = module.html_head() if head_part: html_heads.append(utf8(head_part)) body_part = module.html_body() if body_part: html_bodies.append(utf8(body_part)) if js_files: # Maintain order of JavaScript files given by modules js = self.render_linked_js(js_files) sloc = html.rindex(b‘</body>‘) html = html[:sloc] + utf8(js) + b‘\n‘ + html[sloc:] if js_embed: js = self.render_embed_js(js_embed) sloc = html.rindex(b‘</body>‘) html = html[:sloc] + js + b‘\n‘ + html[sloc:] if css_files: css = self.render_linked_css(css_files) hloc = html.index(b‘</head>‘) html = html[:hloc] + utf8(css) + b‘\n‘ + html[hloc:] if css_embed: css = self.render_embed_css(css_embed) hloc = html.index(b‘</head>‘) html = html[:hloc] + css + b‘\n‘ + html[hloc:] if html_heads: hloc = html.index(b‘</head>‘) html = html[:hloc] + b‘‘.join(html_heads) + b‘\n‘ + html[hloc:] if html_bodies: hloc = html.index(b‘</body>‘) html = html[:hloc] + b‘‘.join(html_bodies) + b‘\n‘ + html[hloc:] self.finish(html)
數據先是保存在html局部變量中,傳入finish中作為參數處理
3.追蹤finish代碼:
def finish(self, chunk=None): """Finishes this response, ending the HTTP request.""" if self._finished: raise RuntimeError("finish() called twice") if chunk is not None: self.write(chunk) # Automatically support ETags and add the Content-Length header if # we have not flushed any content yet. if not self._headers_written: if (self._status_code == 200 and self.request.method in ("GET", "HEAD") and "Etag" not in self._headers): self.set_etag_header() if self.check_etag_header(): self._write_buffer = [] self.set_status(304) if (self._status_code in (204, 304) or (self._status_code >= 100 and self._status_code < 200)): assert not self._write_buffer, "Cannot send body with %s" % self._status_code self._clear_headers_for_304() elif "Content-Length" not in self._headers: content_length = sum(len(part) for part in self._write_buffer) self.set_header("Content-Length", content_length) if hasattr(self.request, "connection"): # Now that the request is finished, clear the callback we # set on the HTTPConnection (which would otherwise prevent the # garbage collection of the RequestHandler when there # are keepalive connections) self.request.connection.set_close_callback(None) self.flush(include_footers=True) self.request.finish() self._log() self._finished = True self.on_finish() self._break_cycles()
數據chunk(即是傳入的html變量)在write方法中又進行處理
4.追蹤write方法:
def write(self, chunk): """Writes the given chunk to the output buffer. To write the output to the network, use the flush() method below. If the given chunk is a dictionary, we write it as JSON and set the Content-Type of the response to be ``application/json``. (if you want to send JSON as a different ``Content-Type``, call set_header *after* calling write()). Note that lists are not converted to JSON because of a potential cross-site security vulnerability. All JSON output should be wrapped in a dictionary. More details at http://haacked.com/archive/2009/06/25/json-hijacking.aspx/ and https://github.com/facebook/tornado/issues/1009 """ if self._finished: raise RuntimeError("Cannot write() after finish()") if not isinstance(chunk, (bytes, unicode_type, dict)): message = "write() only accepts bytes, unicode, and dict objects" if isinstance(chunk, list): message += ". Lists not accepted for security reasons; see " + "http://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.write" raise TypeError(message) if isinstance(chunk, dict): chunk = escape.json_encode(chunk) self.set_header("Content-Type", "application/json; charset=UTF-8") chunk = utf8(chunk) self._write_buffer.append(chunk)
發現數據存放在類成員變量中_write_buffer
若是想在自定義函數中直接輸出該數據,為空
def get(self, *args, **kwargs): import time tm = time.time() self.render(‘home/index.html‘, time=tm) print(self._write_buffer, len(self._write_buffer)) # 為空
因為在finish方法中藍色部分函數flush中對於數據進行了下一步處理:
5.追蹤flush方法(部分源碼):
但是在執行finish時,先要執行flush(部分源碼) def flush(self, include_footers=False, callback=None): """Flushes the current output buffer to the network. The ``callback`` argument, if given, can be used for flow control: it will be run when all flushed data has been written to the socket. Note that only one flush callback can be outstanding at a time; if another flush occurs before the previous flush‘s callback has been run, the previous callback will be discarded. .. versionchanged:: 4.0 Now returns a `.Future` if no callback is given. """ chunk = b"".join(self._write_buffer) self._write_buffer = [] #將列表置為空
所以要想獲取數據:需要進行其他處理,例如:
(1)修改源碼,保存數據
(2)重寫父類函數flush,將數據提前截取保存在新的變量中
為了盡量不修改源碼,可以選擇第二種方法
6.重寫父類函數flush
class IndexHandler(tornado.web.RequestHandler): def flush(self, include_footers=False, callback=None): self._data_html = self._write_buffer super(IndexHandler,self).flush(include_footers,callback)
將數據保存在自己定義的數據_data_html 中
使用時可以直接獲取數據
def get(self, *args, **kwargs): import time tm = time.time() self.render(‘home/index.html‘,time=tm) print(self._data_html)
python---redis緩存頁面前戲之剖析render源碼