溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Django中怎么利用response響應數(shù)據(jù)

發(fā)布時間:2021-07-20 16:11:09 來源:億速云 閱讀:172 作者:Leah 欄目:開發(fā)技術

今天就跟大家聊聊有關Django中怎么利用response響應數(shù)據(jù),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據(jù)這篇文章可以有所收獲。

響應數(shù)據(jù)的返回

在 WSGIHandler.__call__(self, environ, start_response) 方法調用了 WSGIHandler.get_response() 方法, 由此得到響應數(shù)據(jù)對象 response. 如今所要做的, 便是將其返回給客戶端. 在 Django 源碼小剖: 初探 WSGI 中, 簡要的概括了請求到來時 django 自帶服務器的執(zhí)行關系, 摘抄如下:

  • make_server() 中 WSGIServer 類已經(jīng)作為服務器類, 負責接收請求, 調用 application 的處理, 返回相應;

  • WSGIRequestHandler 作為請求處理類, 并已經(jīng)配置在 WSGIServer 中;

  • 接著還設置了 WSGIServer.application 屬性(set_app(app));

  • 返回 server 實例.

  • 接著打開瀏覽器, 即發(fā)起請求. 服務器實例 WSGIServer httpd 調用自身 handle_request() 函數(shù)處理請求. handle_request() 的工作流程如下:請求-->WSGIServer 收到-->調用 WSGIServer.handle_request()-->調用 _handle_request_noblock()-->調用 process_request()-->調用 finish_request()-->finish_request() 中實例化 WSGIRequestHandler-->實例化過程中會調用 handle()-->handle() 中實例化 ServerHandler-->調用 ServerHandler.run()-->run() 調用 application() 這才是真正的邏輯.-->run() 中在調用 ServerHandler.finish_response() 返回數(shù)據(jù)-->回到 process_request() 中調用 WSGIServer.shutdown_request() 關閉請求(其實什么也沒做)

事實上, WSGIServer 并沒有負責將響應數(shù)據(jù)返回給客戶端, 它將客戶端的信息(如最重要的客戶端 socket 套接字)交接給了 WSGIRequestHandler, WSGIRequestHandler 又將客戶端的信息交接給了 ServerHandler, 所以 ServerHandler 產(chǎn)生響應數(shù)據(jù)對象后, 會直接返回給客戶端.

代碼剖析

從「調用 ServerHandler.run()-->run() 調用 application() 這才是真正的邏輯.-->run() 中在調用 ServerHandler.finish_response() 返回數(shù)據(jù)」開始說起, 下面是主要的代碼解說:

# 下面的函數(shù)都在 ServerHandler 的繼承鏈上方法, 有些方法父類只定義了空方法, 具體邏輯交由子類實現(xiàn). 有關繼承鏈請參看: http://daoluan.net/blog/decode-django-wsgi/
def run(self, application):
 """Invoke the application"""
 try:
  self.setup_environ()
  # application 在 django 中就是 WSGIHandler 類, 他實現(xiàn)了 __call__ 方法, 所以行為和函數(shù)一樣.
  self.result = application(self.environ, self.start_response)
  self.finish_response()
 except:
  # handle error
 
def finish_response(self):
 try:
  if not self.result_is_file() or not self.sendfile():
   for data in self.result:
    # 向套接字寫數(shù)據(jù), 將數(shù)據(jù)返回給客戶端
    self.write(data)
   self.finish_content()
 finally:
  self.close()
 
def write(self, data):
 """'write()' callable as specified by PEP 333""" 
 # 必須是都是字符
 assert type(data) is StringType,"write() argument must be string" 
 if not self.status:
  raise AssertionError("write() before start_response()") 
 # 需要先發(fā)送 HTTP 頭
 elif not self.headers_sent:
  # Before the first output, send the stored headers
  self.bytes_sent = len(data) # make sure we know content-length
  self.send_headers()
 # 再發(fā)送實體
 else:
  self.bytes_sent += len(data)
 
 # XXX check Content-Length and truncate if too many bytes written?
 self._write(data)
 self._flush()
 
def write(self, data):
 """'write()' callable as specified by PEP 3333"""
 
 assert isinstance(data, bytes), "write() argument must be bytestring"
 
 # 必須先調用 self.start_response() 設置狀態(tài)碼
 if not self.status:
  raise AssertionError("write() before start_response()")
 
 # 需要先發(fā)送 HTTP 頭
 elif not self.headers_sent:
  # Before the first output, send the stored headers
  self.bytes_sent = len(data) # make sure we know content-length
  self.send_headers()
 # 再發(fā)送實體
 else:
  self.bytes_sent += len(data)
 
 # XXX check Content-Length and truncate if too many bytes written? 是否需要分段發(fā)送過大的數(shù)據(jù)?
 
 # If data is too large, socket will choke, 窒息死掉 so write chunks no larger
 # than 32MB at a time.
 
 # 分片發(fā)送
 length = len(data)
 if length > 33554432:
  offset = 0
  while offset < length:
   chunk_size = min(33554432, length)
   self._write(data[offset:offset+chunk_size])
   self._flush()
   offset += chunk_size
 else:
  self._write(data)
  self._flush()
 
def _write(self,data):
 # 如果是第一次調用, 則調用 stdout.write(), 理解為一個套接字對象
 self.stdout.write(data) 
 # 第二次調用就是直接調用 stdout.write() 了
 self._write = self.stdout.write

看完上述內容,你們對Django中怎么利用response響應數(shù)據(jù)有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI