日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

我們?cè)谑褂肞ython的一些庫(kù)時(shí),會(huì)遇到中間件這個(gè)概念,比如scrapy和Django,那么什么是中間件呢?

什么是中間件

中間件就是在目標(biāo)結(jié)果之間進(jìn)行的額外處理過(guò)程,在Django中就是request和response之間進(jìn)行的處理,相對(duì)來(lái)說(shuō)實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,但是要注意它是對(duì)全局有效的,可以在全局范圍內(nèi)改變輸入和輸出結(jié)果,因此需要謹(jǐn)慎使用,否則不僅會(huì)造成難以定位的錯(cuò)誤,而且可能會(huì)影響整體性能。

中間件有什么用

如果想要修改HttpRequest或者HttpResponse,就可以通過(guò)中間件來(lái)實(shí)現(xiàn)。

  • 登陸認(rèn)證:在中間件中加入登陸認(rèn)證,所有請(qǐng)求就自動(dòng)擁有登陸認(rèn)證,如果需要放開(kāi)部分路由,只需要特殊處理就可以了。
  • 流量統(tǒng)計(jì):可以針對(duì)一些渲染頁(yè)面統(tǒng)計(jì)訪問(wèn)流量。
  • 惡意請(qǐng)求攔截:統(tǒng)計(jì)IP請(qǐng)求次數(shù),可以進(jìn)行頻次限制或者封禁IP。

中間件執(zhí)行流程

在Django中自定義中間件是非常簡(jiǎn)單的,在settings.py中有一個(gè)配置項(xiàng):

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

只要把添加的中間件配置在這里就可以了。每一個(gè)中間件都是一個(gè)類(lèi),多個(gè)中間件可以寫(xiě)在同一個(gè)文件,也可以在獨(dú)立文件中。每個(gè)中間件可以包含五個(gè)方法:

process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

我在網(wǎng)上找到這么一張圖片,說(shuō)明了請(qǐng)求的數(shù)據(jù)流在Django中間件當(dāng)中的執(zhí)行流程

Django中間件看完這篇徹底明白

 

中間件函數(shù)執(zhí)行流程

  • 請(qǐng)求到達(dá)中間件后先依次執(zhí)行每個(gè)中間件的process_request函數(shù)
  • 然后再依次執(zhí)行每個(gè)中間件的process_view函數(shù),找到我們的視圖函數(shù)
  • 執(zhí)行視圖函數(shù)處理請(qǐng)求數(shù)據(jù)
  • 如果在上面的過(guò)程中出現(xiàn)異常,則依次反方向執(zhí)行每個(gè)中間件的process_exception函數(shù)
  • 如果請(qǐng)求包含模板渲染,則依次反方向執(zhí)行每個(gè)中間件的process_template_response函數(shù)
  • 最后依次反方向執(zhí)行每個(gè)中間件的process_response函數(shù)

以上這些執(zhí)行函數(shù)將返回None或者HttpResponse對(duì)象,如果返回None,則交給下一個(gè)中間件的對(duì)應(yīng)函數(shù)處理;如果返回HttpResponse對(duì)象,則將其返回給用戶(hù)

在這些中間件的執(zhí)行函數(shù)中,我們最常用的就是process_request和process_response函數(shù),通常用來(lái)在視圖函數(shù)處理前和視圖函數(shù)處理后執(zhí)行一些相應(yīng)的操作,這個(gè)要根據(jù)我們的業(yè)務(wù)需求,選擇不同的處理過(guò)程。例如:進(jìn)行登陸認(rèn)證,因?yàn)楸仨氁谝晥D函數(shù)處理前進(jìn)行認(rèn)證,我們可以在process_request中處理;攜帶認(rèn)證cookies信息,就可以在process_response函數(shù)中給response對(duì)象增加指定cookies值。

中間件回調(diào)函數(shù)執(zhí)行

  • Request函數(shù):process_request(self, request)
    執(zhí)行時(shí)機(jī):當(dāng)接收到前端請(qǐng)求,并生成request對(duì)象,但是仍未解析url,未確定當(dāng)前要運(yùn)行的視圖函數(shù)。
    如果返回None,Django將繼續(xù)處理下一個(gè)中間件的request函數(shù);如果返回HttpResponse對(duì)象,Django將不再執(zhí)行其他除process_response以外的所有函數(shù),包括后面的process_request函數(shù)其他中間件函數(shù)以及視圖函數(shù)
  • View函數(shù):process_view(self, request, callback, callback_args, callback_kwargs)
    執(zhí)行時(shí)機(jī):在執(zhí)行完所有中間件的process_request函數(shù),并且已經(jīng)匹配到要執(zhí)行的視圖函數(shù),但是還沒(méi)有調(diào)用視圖函數(shù)之前。
    callback:時(shí)機(jī)要執(zhí)行的視圖函數(shù)對(duì)象(就是我們所寫(xiě)的視圖處理函數(shù))
    callback_args:視圖函數(shù)的位置參數(shù)列表(不包含self和request)
    callback_kwargs:視圖函數(shù)的關(guān)鍵字參數(shù)
    如果返回None,Django將繼續(xù)處理下一個(gè)中間件的request函數(shù);如果返回HttpResponse對(duì)象,Django將不再執(zhí)行其他除process_response以外的所有函數(shù),包括后面的process_request函數(shù)其他中間件函數(shù)以及視圖函數(shù)
  • Template函數(shù):process_template_response()
    執(zhí)行時(shí)機(jī):只有在視圖函數(shù)的返回對(duì)象中有render方法才會(huì)執(zhí)行,并把render方法的返回值返回給用戶(hù)。
  • Exception函數(shù):process_exception(self, request, exception)
    執(zhí)行時(shí)機(jī):如果在執(zhí)行過(guò)程中出現(xiàn)問(wèn)題,并且拋出一個(gè)未被捕獲的異常時(shí)才被調(diào)用。我們可以用它來(lái)捕獲請(qǐng)求錯(cuò)誤,發(fā)送通知或者恢復(fù)錯(cuò)誤場(chǎng)景。
    如果返回None,Django將使用框架內(nèi)置異常處理,并繼續(xù)交給下一個(gè)exception函數(shù);如果返回HttpResponse對(duì)象,Django將不再執(zhí)行其他除process_response以外的所有函數(shù),并中斷異常處理。
  • Response函數(shù):process_response(self, request, response)
    執(zhí)行時(shí)機(jī):執(zhí)行完view函數(shù)并生成response之后,幾乎是必執(zhí)行的函數(shù)。
    返回并且只能必須返回HttpResponse對(duì)象,否則會(huì)導(dǎo)致HTTP請(qǐng)求中斷。

自定義中間件

  • 創(chuàng)建中間件類(lèi)
from django.utils.deprecation import MiddlewareMixin

class MyCustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print('MyCustomMiddleware1')

    def process_response(self, request, response):
        print('返回 MyCustomMiddleware1')
        return response

class MyCustomMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print('MyCustomMiddleware2')

    def process_response(self, request, response):
        print('返回 MyCustomMiddleware2')
        return response
  • 注冊(cè)中間件
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'MyMiddleware.MyCustomMiddleware1',
    'MyMiddleware.MyCustomMiddleware2'
]

輸出結(jié)果:

MyCustomMiddleware1
MyCustomMiddleware2
返回 MyCustomMiddleware2
返回 MyCustomMiddleware1

系統(tǒng)中間件的用途

  • django.middleware.security.SecurityMiddleware主要是針對(duì)安全訪問(wèn)處理,就是把http請(qǐng)求重定向到https請(qǐng)求
  • django.contrib.sessions.middleware.SessionMiddleware在Django中我們用的request.session就是在process_request中進(jìn)行處理的,根據(jù)我們?cè)趕ettings中配置的SESSION_COOKIE_NAME變量,從cookies中獲取對(duì)應(yīng)的值,從表中查詢(xún)出session值,創(chuàng)建session對(duì)象,賦值給request_session對(duì)象。
def process_request(self, request):
    session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
    request.session = self.SessionStore(session_key)

process_response函數(shù)中,給response對(duì)象設(shè)置SESSION_COOKIE_NAME值和過(guò)期時(shí)間等。

response.set_cookie(
   settings.SESSION_COOKIE_NAME,
   request.session.session_key, max_age=max_age,
   expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
   path=settings.SESSION_COOKIE_PATH,
   secure=settings.SESSION_COOKIE_SECURE or None,
   httponly=settings.SESSION_COOKIE_HTTPONLY or None,
   samesite=settings.SESSION_COOKIE_SAMESITE
)
  • django.middleware.common.CommonMiddleware
    檢測(cè)是否允許瀏覽器類(lèi)型
if 'HTTP_USER_AGENT' in request.META:
    for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
        if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
            raise PermissionDenied('Forbidden user agent')

檢查是否需要添加/,主要是根據(jù)settings中AppEND_SLASH配置

if self.should_redirect_with_slash(request):
    path = self.get_full_path_with_slash(request)
else:
    path = request.get_full_path()

在process_response函數(shù)中,會(huì)判斷是否需要把404的請(qǐng)求重新定向到我們需要的頁(yè)面

  • django.middleware.csrf.CsrfViewMiddleware
    這個(gè)很明顯就是我們Django框架的csrf驗(yàn)證了,主要是process_view中的處理,從函數(shù)處理我們可以看到以下幾點(diǎn):
  1. request請(qǐng)求中包含csrf_processing_done屬性,則不進(jìn)行csrf驗(yàn)證
  2. 視圖函數(shù)中包含csrf_exempt屬性,則不進(jìn)行csrf驗(yàn)證
  3. 如果是GET、HEAD、OPTIONS、TRACE請(qǐng)求,則不進(jìn)行csrf驗(yàn)證
  4. request請(qǐng)求中包含_dont_enforce_csrf_checks屬性,則不進(jìn)行csrf驗(yàn)證
  5. https請(qǐng)求頭中如果不包含HTTP_REFERER,則拒絕訪問(wèn)
  6. 請(qǐng)求頭中不包含CSRF_COOKIE,則拒絕訪問(wèn)
  7. POST請(qǐng)求中攜帶csrfmiddlewaretoken參數(shù),如果驗(yàn)證通過(guò)就可以訪問(wèn)
  8. PUT/DELETE請(qǐng)求頭中攜帶CSRF_HEADER_NAME配置,如果驗(yàn)證通過(guò)就可以訪問(wèn)
  • django.contrib.auth.middleware.AuthenticationMiddleware這個(gè)中間件中為我們的request對(duì)象添加了user屬性,主要是獲取session中SESSION_KEY值(settings配置中),從用戶(hù)表中查詢(xún)對(duì)應(yīng)主鍵,得到用戶(hù)對(duì)象,將其付給request.user
  • django.contrib.messages.middleware.MessageMiddlewareDjango的消息框架,主要是向目標(biāo)中推送消息內(nèi)容,在前端可通過(guò)以下方式使用
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}" {% endif %}>
        {% if mesage.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
        {{ message }}
    </li>
    {% endfor %}
</ul>
{% endif %}

分享到:
標(biāo)簽:Django
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定