国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 分析Python的Django框架的運行方式及處理流程

分析Python的Django框架的運行方式及處理流程

2020-06-02 09:52吳文苑 Python

這篇文章主要介紹了分析Python的Django框架的運行方式及處理流程,本文對于Django框架的機制總結得非常之直觀精煉,極力推薦!需要的朋友可以參考下

之前在網上看過一些介紹Django處理請求的流程和Django源碼結構的文章,覺得了解一下這些內容對開發Django項目還是很有幫助的。所以,我按照自己的邏輯總結了一下Django項目的運行方式和對Request的基本處理流程。


一、Django的運行方式

運行Django項目的方法很多,這里主要介紹一下常用的方法。一種是在開發和調試中經常用到runserver方法,使用Django自己的web server;另外一種就是使用fastcgi,uWSGIt等協議運行Django項目,這里以uWSGIt為例。

1、runserver方法

runserver方法是調試Django時經常用到的運行方式,它使用Django自帶的WSGI Server運行,主要在測試和開發中使用,使用方法如下:

?
1
2
3
4
Usage: manage.py runserver [options] [optional port number, or ipaddr:port]
# python manager.py runserver  # default port is 8000
# python manager.py runserver 8080
# python manager.py runserver 127.0.0.1:9090

看一下manager.py的源碼,你會發現上面的命令其實是通過Django的execute_from_command_line方法執行了內部實現的runserver命令,那么現在看一下runserver具體做了什么。。

看了源碼之后,可以發現runserver命令主要做了兩件事情:

    1). 解析參數,并通過django.core.servers.basehttp.get_internal_wsgi_application方法獲取wsgi handler;

    2). 根據ip_address和port生成一個WSGIServer對象,接受用戶請求

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
get_internal_wsgi_application的源碼如下:
def get_internal_wsgi_application():
  """
  Loads and returns the WSGI application as configured by the user in
  ``settings.WSGI_APPLICATION``. With the default ``startproject`` layout,
  this will be the ``application`` object in ``projectname/wsgi.py``.
 
  This function, and the ``WSGI_APPLICATION`` setting itself, are only useful
  for Django's internal servers (runserver, runfcgi); external WSGI servers
  should just be configured to point to the correct application object
  directly.
 
  If settings.WSGI_APPLICATION is not set (is ``None``), we just return
  whatever ``django.core.wsgi.get_wsgi_application`` returns.
 
  """
  from django.conf import settings
  app_path = getattr(settings, 'WSGI_APPLICATION')
  if app_path is None:
    return get_wsgi_application()
 
  return import_by_path(
    app_path,
    error_prefix="WSGI application '%s' could not be loaded; " % app_path
  )

通過上面的代碼我們可以知道,Django會先根據settings中的WSGI_APPLICATION來獲取handler;在創建project的時候,Django會默認創建一個wsgi.py文件,而settings中的WSGI_APPLICATION配置也會默認指向這個文件。看一下這個wsgi.py文件,其實它也和上面的邏輯一樣,最終調用get_wsgi_application實現。

2、uWSGI方法

uWSGI+Nginx的方法是現在最常見的在生產環境中運行Django的方法,本人的博客也是使用這種方法運行,要了解這種方法,首先要了解一下WSGI和uWSGI協議。

WSGI,全稱Web Server Gateway Interface,或者Python Web Server Gateway Interface,是為Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口,基于現存的CGI標準而設計的。WSGI其實就是一個網關(Gateway),其作用就是在協議之間進行轉換。(PS: 這里只對WSGI做簡單介紹,想要了解更多的內容可自行搜索)

uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。注意uwsgi是一種通信協議,而uWSGI是實現uwsgi協議和WSGI協議的Web服務器。uWSGI具有超快的性能、低內存占用和多app管理等優點。以我的博客為例,uWSGI的xml配置如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<uwsgi>
  <!-- 端口 -->
  <socket>:7600</socket>
  <stats>:40000</stats>
  <!-- 系統環境變量 -->
  <env>DJANGO_SETTINGS_MODULE=geek_blog.settings</env>
  <!-- 指定的python WSGI模塊 -->
  <module>django.core.handlers.wsgi:WSGIHandler()</module>
  <processes>6</processes>
  <master />
  <master-as-root />
  <!-- 超時設置 -->
  <harakiri>60</harakiri>
  <harakiri-verbose/>
  <daemonize>/var/app/log/blog/uwsgi.log</daemonize>
  <!-- socket的監聽隊列大小 -->
  <listen>32768</listen>
  <!-- 內部超時時間 -->
  <socket-timeout>60</socket-timeout>
</uwsgi>

以上就是uWSGI xml配置的寫法,也可以使用ini的方式。安裝uWSGI和運行的命令如下:

?
1
2
sudo pip install uwsgi
uwsgi --pidfile=/var/run/geek-blog.pid -x uwsgi.xml --uid blog --gid nogroup

uWSGI和Nginx一起使用的配置方法就不在這里說明了,網上教程很多,需要的可以自行搜索。


二、HTTP請求處理流程

Django和其他Web框架一樣,HTTP的處理流程基本類似:接受request,返回response內容。Django的具體處理流程大致如下圖所示:

1、加載project settings

在通過django-admin.py創建project的時候,Django會自動生成默認的settings文件和manager.py等文件,在創建WSGIServer之前會執行下面的引用:
from django.conf import settings

上面引用在執行時,會讀取os.environ中的DJANGO_SETTINGS_MODULE配置,加載項目配置文件,生成settings對象。所以,在manager.py文件中你可以看到,在獲取WSGIServer之前,會先將project的settings路徑加到os路徑中。

2、創建WSGIServer

不管是使用runserver還是uWSGI運行Django項目,在啟動時都會調用django.core.servers.basehttp中的run()方法,創建一個django.core.servers.basehttp.WSGIServer類的實例,之后調用其serve_forever()方法啟動HTTP服務。run方法的源碼如下:

?
1
2
3
4
5
6
7
8
9
10
def run(addr, port, wsgi_handler, ipv6=False, threading=False):
  server_address = (addr, port)
  if threading:
    httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
  else:
    httpd_cls = WSGIServer
  httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
  # Sets the callable application as the WSGI application that will receive requests
  httpd.set_app(wsgi_handler)
  httpd.serve_forever()

如上,我們可以看到:在創建WSGIServer實例的時候會指定HTTP請求的Handler,上述代碼使用WSGIRequestHandler。當用戶的HTTP請求到達服務器時,WSGIServer會創建WSGIRequestHandler實例,使用其handler方法來處理HTTP請求(其實最終是調用wsgiref.handlers.BaseHandler中的run方法處理)。WSGIServer通過set_app方法設置一個可調用(callable)的對象作為application,上面提到的handler方法最終會調用設置的application處理request,并返回response。

其中,WSGIServer繼承自wsgiref.simple_server.WSGIServer,而WSGIRequestHandler繼承自wsgiref.simple_server.WSGIRequestHandler,wsgiref是Python標準庫給出的WSGI的參考實現。其源碼可自行到wsgiref參看,這里不再細說。

3、處理Request

第二步中說到的application,在Django中一般是django.core.handlers.wsgi.WSGIHandler對象,WSGIHandler繼承自django.core.handlers.base.BaseHandler,這個是Django處理request的核心邏輯,它會創建一個WSGIRequest實例,而WSGIRequest是從http.HttpRequest繼承而來

4、返回Response

上面提到的BaseHandler中有個get_response方法,該方法會先加載Django項目的ROOT_URLCONF,然后根據url規則找到對應的view方法(類),view邏輯會根據request實例生成并返回具體的response。

在Django返回結果之后,第二步中提到wsgiref.handlers.BaseHandler.run方法會調用finish_response結束請求,并將內容返回給用戶。


三、Django處理Request的詳細流程

上述的第三步和第四步邏輯只是大致說了一下處理過程,Django在處理request的時候其實做了很多事情,下面我們詳細的過一下。首先給大家分享兩個網上看到的Django流程圖:

分析Python的Django框架的運行方式及處理流程

Django流程圖1

分析Python的Django框架的運行方式及處理流程

Django流程圖2
上面的兩張流程圖可以大致描述Django處理request的流程,按照流程圖2的標注,可以分為以下幾個步驟:

    1. 用戶通過瀏覽器請求一個頁面

    2. 請求到達Request Middlewares,中間件對request做一些預處理或者直接response請求

    3. URLConf通過urls.py文件和請求的URL找到相應的View

    4. View Middlewares被訪問,它同樣可以對request做一些處理或者直接返回response

    5. 調用View中的函數

    6. View中的方法可以選擇性的通過Models訪問底層的數據

    7. 所有的Model-to-DB的交互都是通過manager完成的

    8. 如果需要,Views可以使用一個特殊的Context

    9. Context被傳給Template用來生成頁面

    a. Template使用Filters和Tags去渲染輸出

    b. 輸出被返回到View

    c. HTTPResponse被發送到Response Middlewares

    d. 任何Response Middlewares都可以豐富response或者返回一個完全不同的response

    e. Response返回到瀏覽器,呈現給用戶

上述流程中最主要的幾個部分分別是:Middleware(中間件,包括request, view, exception, response),URLConf(url映射關系),Template(模板系統),下面一一介紹一下。

1、Middleware(中間件)

Middleware并不是Django所獨有的東西,在其他的Web框架中也有這種概念。在Django中,Middleware可以滲入處理流程的四個階段:request,view,response和exception,相應的,在每個Middleware類中都有rocess_request,process_view, process_response 和 process_exception這四個方法。你可以定義其中任意一個活多個方法,這取決于你希望該Middleware作用于哪個處理階段。每個方法都可以直接返回response對象。

Middleware是在Django BaseHandler的load_middleware方法執行時加載的,加載之后會建立四個列表作為處理器的實例變量:

  1.     _request_middleware:process_request方法的列表
  2.     _view_middleware:process_view方法的列表
  3.     _response_middleware:process_response方法的列表
  4.     _exception_middleware:process_exception方法的列表

Django的中間件是在其配置文件(settings.py)的MIDDLEWARE_CLASSES元組中定義的。在MIDDLEWARE_CLASSES中,中間件組件用字符串表示:指向中間件類名的完整Python路徑。例如GeekBlog項目的配置:

?
1
2
3
4
5
6
7
8
9
10
11
MIDDLEWARE_CLASSES = (
  'django.middleware.cache.UpdateCacheMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.cache.FetchFromCacheMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.locale.LocaleMiddleware',
  'geek_blog.middlewares.MobileDetectionMiddleware'# 自定義的Middleware
)

Django項目的安裝并不強制要求任何中間件,如果你愿意,MIDDLEWARE_CLASSES可以為空。中間件出現的順序非常重要:在request和view的處理階段,Django按照MIDDLEWARE_CLASSES中出現的順序來應用中間件,而在response和exception異常處理階段,Django則按逆序來調用它們。也就是說,Django將MIDDLEWARE_CLASSES視為view函數外層的順序包裝子:在request階段按順序從上到下穿過,而在response則反過來。以下兩張圖可以更好地幫助你理解:

分析Python的Django框架的運行方式及處理流程

Django Middleware流程1

分析Python的Django框架的運行方式及處理流程

Django Middleware流程圖2
2、URLConf(URL映射)

如果處理request的中間件都沒有直接返回response,那么Django會去解析用戶請求的URL。URLconf就是Django所支撐網站的目錄。它的本質是URL模式以及要為該URL模式調用的視圖函數之間的映射表。通過這種方式可以告訴Django,對于這個URL調用這段代碼,對于那個URL調用那段代碼。具體的,在Django項目的配置文件中有ROOT_URLCONF常量,這個常量加上根目錄"/",作為參數來創建django.core.urlresolvers.RegexURLResolver的實例,然后通過它的resolve方法解析用戶請求的URL,找到第一個匹配的view。

其他有關URLConf的內容,這里不再具體介紹,大家可以看DjangoBook了解。

3、Template(模板)

大部分web框架都有自己的Template(模板)系統,Django也是。但是,Django模板不同于Mako模板和jinja2模板,在Django模板不能直接寫Python代碼,只能通過額外的定義filter和template tag實現。由于本文主要介紹Django流程,模板內容就不過多介紹。


PS: 以上代碼和內容都是基于Django 1.6.5版本,其他版本可能與其不同,請參考閱讀。


Over!

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产在线精品一区 | 人人99 | 国产精品美女久久久久aⅴ国产馆 | 快色视频在线观看 | 狠狠色噜噜狠狠狠8888米奇 | 中文字幕一区在线 | 97国产精品视频 | 久久久久久久久久久久99 | 亚洲精品久久久久一区二区三区 | 毛片一级在线 | 欧美人妖在线 | www国产亚洲精品久久网站 | a国产精品| 精品国产精品三级精品av网址 | 91中文字幕 | 无码一区二区三区视频 | 韩日中文字幕 | 九九九久久国产免费 | 久久久久久一区二区三区 | 欧美一级特黄aaaaaaa在线观看 | yiren22成人网 | 日韩成人一区 | 成人看片免费 | 久久精品无码一区二区日韩av | 欧美黄色一级片免费看 | 日韩成人在线免费视频 | 亚洲精品二区三区 | 日本精品在线播放 | 天堂在线中文字幕 | 欧美人成在线观看 | 日韩精品一区二区在线观看 | 国产精品区一区二区三含羞草 | 一级片免费视频 | 天天操天天操 | 黑人精品欧美一区二区蜜桃 | 亚洲精品一区二区 | 欧美成在线视频 | 在线视频91 | 欧美激情一区二区三级高清视频 | 国产精品久久国产精品 | 国产精品区一区二区三区 |