Django 的請求對象WSGIRequest

Django 的請求對象WSGIRequest

Django的WSGIRequest

class WSGIRequest(HttpRequest):
    def __init__(self, environ):
        script_name = get_script_name(environ)
        path_info = get_path_info(environ)
        if not path_info:
            path_info = '/'
        self.environ = environ
        self.path_info = path_info
        self.path = '%s/%s' % (script_name.rstrip('/'),
                               path_info.replace('/', '', 1))
        self.META = environ
        self.META['PATH_INFO'] = path_info
        self.META['SCRIPT_NAME'] = script_name
        self.method = environ['REQUEST_METHOD'].upper()
        self.content_type, self.content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
        ...
        self._post_parse_error = False
        ...
        self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
        self._read_started = False
        self.resolver_match = None

    def _get_scheme(self):
        return self.environ.get('wsgi.url_scheme')
    
    # 在視圖函數(shù)中調(diào)用request.GET時才會真正的把environ中的wsgi.input對象中的響應(yīng)報文的請求參數(shù)給返回出來榕酒,然后保存在request實例屬性GET中胚膊,下次再取參數(shù)的時候就會直接從request.__dict__['GET']得到GET請求的參數(shù)
    @cached_property
    def GET(self):
        # The WSGI spec says 'QUERY_STRING' may be absent.
        raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
        return QueryDict(raw_query_string, encoding=self._encoding)

    def _get_post(self):
        if not hasattr(self, '_post'):
            self._load_post_and_files()
        return self._post

    def _set_post(self, post):
        self._post = post

    @cached_property
    def COOKIES(self):
        raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
        return parse_cookie(raw_cookie)

    @property
    def FILES(self):
        if not hasattr(self, '_files'):
            self._load_post_and_files()
        return self._files

    POST = property(_get_post, _set_post)

GETPOST想鹰, COOKIES紊婉, FILES這幾個是非數(shù)據(jù)屬性描述符,在request被實例化出來的時候并不是request的實例屬性辑舷,而是在request.GET/POST/COOKIES/FILES時才去實際把這些請求參數(shù)或者cookie或者上傳的文件 從wsgi.input中讀取出來封裝成QueryDictMultiValueDict類型的實例對象肩榕,同時會把這些QueryDict和MultiValueDict對象保存在request的實例屬性中,下次再調(diào)用request.GET/POST/COOKIES/FILES時就直接從request.__dict__中取出即可惩妇。

本質(zhì)上是一種懶加載機制+緩存的機制株汉,只有當(dāng)用到的時候才去真正執(zhí)行取參數(shù)的操作,然后再把取得參數(shù)結(jié)果保存在request對象的實例屬性中歌殃。

django的application對象

class WSGIHandler(base.BaseHandler):

    # WSGIRequest類是django自己提供的請求類乔妈,實例化之后就是request對象
    request_class = WSGIRequest

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 加載中間件實例到內(nèi)存中,此時中間件實例的各種方法已經(jīng)被包裹在 _get_response() 方法的前后了
        self.load_middleware()

    def __call__(self, environ, start_response):
        set_script_prefix(get_script_name(environ))
        signals.request_started.send(sender=self.__class__, environ=environ)

        # 實例化WSGIRequest氓皱,得到request對象路召,request對象中此時并沒有session屬性,而是在中間件加載后波材,
        # 請求進(jìn)入session中間件時股淡,在session中間件的process_request()方法中動態(tài)添加的session屬性
        request = self.request_class(environ)
        response = self.get_response(request)

        response._handler_class = self.__class__

        status = '%d %s' % (response.status_code, response.reason_phrase)
        response_headers = list(response.items())
        for c in response.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        start_response(status, response_headers)
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
        return response

對于Web框架來說,它負(fù)責(zé)把environ中的wsgi.input中內(nèi)容進(jìn)行解析廷区,因為wsgi.input這個對象中含有客戶端發(fā)送過來的HTTP請求報文唯灵,解析了請求報文就可以拿到客戶端傳遞的參數(shù)信息已經(jīng)文件等。然后把這些有用的參數(shù)都保存在request對象的實例屬性中隙轻。

對于Web服務(wù)器來說埠帕,它負(fù)責(zé)把接受客戶端的連接垢揩,然后把客戶端發(fā)送的http報文封裝到envion的wsgi.input字段中,然后把這個environ和一個回調(diào)函數(shù)start_response傳入到web框架的入口application中敛瓷,然后調(diào)用application(environ, start_response)返回一個response對象叁巨,最后再把取出response對象中的數(shù)據(jù),構(gòu)造成HTTP響應(yīng)報文發(fā)送到客戶端呐籽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锋勺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狡蝶,更是在濱河造成了極大的恐慌宙刘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牢酵,死亡現(xiàn)場離奇詭異悬包,居然都是意外死亡,警方通過查閱死者的電腦和手機馍乙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門布近,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丝格,你說我怎么就攤上這事撑瞧。” “怎么了显蝌?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵预伺,是天一觀的道長。 經(jīng)常有香客問我曼尊,道長酬诀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任骆撇,我火速辦了婚禮瞒御,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘神郊。我一直安慰自己肴裙,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布涌乳。 她就那樣靜靜地躺著蜻懦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夕晓。 梳的紋絲不亂的頭發(fā)上宛乃,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音,去河邊找鬼烤惊。 笑死乔煞,一個胖子當(dāng)著我的面吹牛吁朦,可吹牛的內(nèi)容都是我干的柒室。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逗宜,長吁一口氣:“原來是場噩夢啊……” “哼雄右!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纺讲,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤擂仍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后熬甚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢渔,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年乡括,在試婚紗的時候發(fā)現(xiàn)自己被綠了肃廓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡诲泌,死狀恐怖盲赊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情敷扫,我是刑警寧澤哀蘑,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站葵第,受9級特大地震影響绘迁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卒密,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一脊髓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧栅受,春花似錦将硝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至而芥,卻和暖如春律罢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工误辑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沧踏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓巾钉,卻偏偏與公主長得像翘狱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砰苍,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容