1. Initial code:
Get (Self, *args, * *Kwargs): import time = time.time () self.render ('home/ index.html', TIME=TM)
2. Code Trace Render:
# The first time the Get method is executed, the data has been generated through the Render method, where there is a specific place, see source Def render (self, template_name,**Kwargs):"""renders the template with the given arguments as the response.""" ifself._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= [] forModuleinchGetAttr (Self,"_active_modules", {}). VALUES (): Embed_part=Module.embedded_javascript ()ifembed_part:js_embed.append (UTF8 (embed_part)) File_part=module.javascript_files ()ifFile_part:ifisinstance (File_part, (Unicode_type, bytes)): Js_files.append (File_part)Else: Js_files.extend (file_part) Embed_part=module.embedded_css ()ifembed_part:css_embed.append (UTF8 (embed_part)) File_part=module.css_files ()ifFile_part:ifisinstance (File_part, (Unicode_type, bytes)): Css_files.append (File_part)Else: Css_files.extend (file_part) Head_part=Module.html_head ()ifhead_part:html_heads.append (UTF8 (head_part)) Body_part=module.html_body ()ifbody_part:html_bodies.append (UTF8 (body_part))ifJs_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:]ifJs_embed:js=Self.render_embed_js (js_embed) Sloc= Html.rindex (b'</body>') HTML= Html[:sloc] + js + b'\ n'+Html[sloc:]ifCss_files:css=self.render_linked_css (css_files) Hloc= Html.index (b'') HTML= Html[:hloc] + UTF8 (CSS) + b'\ n'+Html[hloc:]ifCss_embed:css=self.render_embed_css (css_embed) Hloc= Html.index (b'') HTML= Html[:hloc] + CSS + b'\ n'+Html[hloc:]ifHtml_heads:hloc= Html.index (b'') HTML= Html[:hloc] + b"'. Join (Html_heads) + b'\ n'+Html[hloc:]ifHtml_bodies:hloc= Html.index (b'</body>') HTML= Html[:hloc] + b"'. Join (html_bodies) + b'\ n'+Html[hloc:] self.finish (HTML)
The data is stored in the HTML local variable, which is passed into the finish as a parameter processing
3. Follow the finish code:
def finish (self, chunk=None):"""finishes this response, ending the HTTP request.""" ifself._finished:raise RuntimeError ("finish () called Twice") if chunk isNot None:self.write (chunk) # automatically support Etags and add the Content-length Headerif# We have no flushed any content yet. ifNot Self._headers_written:if(Self._status_code = = $and Self.request.methodinch("GET","HEAD") and"Etag"Notinchself._headers): Self.set_etag_header ()ifSelf.check_etag_header (): Self._write_buffer=[] Self.set_status (304) if(Self._status_codeinch(204,304) or (Self._status_code>= -< Self._status_code $): Assert not Self._write_buffer,"cannot send body with%s"%self._status_code self._clear_headers_for_304 () elif"Content-length"NotinchSelf._headers:content_length= SUM (len (part) forPartinchself._write_buffer) Self.set_header ("Content-length", Content_length)ifHasattr (Self.request,"Connection"): # Now that the request isfinished, clear the callback we #SetOn the httpconnection (which would otherwise prevent the # garbage collection of the RequestHandler when T Here # is 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 ()
Data chunk (that is, an incoming HTML variable) is processed in the Write method
4. Follow the Write method:
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 isA dictionary, we write it asJSON andSetThe Content-type of the response to be ' application/json '. (ifWant to send JSON asA different ' content-Type ', call Set_header*after*calling Write ()). Note that lists is not converted to JSON because of a potential cross-site security vulnerability. All JSON output should is wrappedincha dictionary. More details at http://Haacked.com/archive/2009/06/25/json-hijacking.aspx/andHttps//github.com/facebook/tornado/issues/1009 """ ifself._finished:raise RuntimeError ("cannot write () after finish ()") ifNot isinstance (chunk, (bytes, unicode_type, dict)): Message="write () only accepts bytes, Unicode, and Dict objects" ifisinstance (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)ifisinstance (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)
The discovery data is stored in the class member variable _write_buffer
If you want to output the data directly in a custom function, empty
Get (Self, *args, * *Kwargs): import time = time.time () self.render ('home/ index.html', Time=tm) print (Self._write_buffer, Len (self._write_buffer)) # is empty
Because in the finish method, the blue part of the function flush in the next process for the data:
5. Follow the Flush method (some source code):
However, when performing the finish, the flush (part source) def flush (self, include_footers=false, callback=None):"""Flushes the current output of buffer to the network.the ' callback ' argument,ifGiven, can be used forFlow control:it would be run if all flushed data have been written to the socket. Note that only one flush callback can is outstanding at a time; ifAnother flush occurs before the previous flush'S Callbackhas been run, the previous callback would be discarded. .. Versionchanged::4.0Now returns a '. Future 'ifNo callback isgiven. """Chunk = b"". Join (Self._write_buffer) self._write_buffer = []#将列表置为空
So to get the data: Additional processing is required, such as:
(1) Modify the source code, save the data
(2) Overriding the parent function flush, saving the data in advance in the new variable
To try not to modify the source code, you can choose the second method
6. overriding the parent class function flush
class Indexhandler (Tornado.web.RequestHandler): def flush (self, include_footers=false, callback=None): = self._write_buffer super (indexhandler,self). Flush (Include_footers,callback)
Save data in your own defined data _data_html
Direct access to data when used
Get (Self, *args, * *Kwargs): import time = time.time () self.render (' home/index.html ', Time=tm) print (self._data_html)
Python---redis cache page Analysis of the play in front of the render source code