全面解讀Python Web開發框架Django,利用Django構建web應用及其部署

全面解讀Python Web開發框架Django

Django是一個開源的Web應用框架,由Python寫成。採用MVC的軟件設計模式,主要目標是使得開發複雜的、數據庫驅動的網站變得簡單。Django注重組件的重用性和「可插拔性」,敏捷開發和DRY法則(Don’t Repeat Yoursef)。
 

花了兩週時間,利用工做間隙時間,開發了一個基於Django的項目任務管理Web應用。項目計劃的實時動態,能夠方便地被項目成員查看(^_^又 重複發明輪子了)。從前臺到後臺,好好折騰了一把,用到:HTML、CSS、JavaScript、Apache、Python、mod_wsgi、 Django。很久不用CSS和JavaScript了,感到有點生疏了,查了無數次手冊。後臺Django開發環境的搭建也花了很多時間和精力。記錄下 來,省得之後走彎路。同時給你們推薦一下Django框架,若是你想很是快速地編寫本身的web應用,能夠考慮使用Django,同時Django還會給 你提供一個功能強大的後臺管理界面。php

Django是一個開源的Web應用框架,由Python寫成。採用MVC的軟件設計模式,主要目標是使得開發複雜的、數據庫驅動的網站變得簡單。 Django注重組件的重用性和「可插拔性」,敏捷開發和DRY法則(Don't Repeat Yoursef)。在Django中Python被廣泛使用,甚至包括配置文件和數據模型。它能夠運行在啓用了mod_python或mod_wsgi的 Apache2,或者任何兼容WSGI(Web Server Gataway Interface)的Web服務器。css

1. Django的快速開發html

第一步(Model):設計本身的數據模型。
第二步(View):建立網頁模板。Django本身的Html模板語言,很是容易將數據和模板結合起來,建立動態頁面。
第三步(Control):定義URL,提供服務和控制。
入門教程: https://docs.djangoproject.com/en/1.4/intro/tutorial01/前端

2. Django開發環境的搭建python

Django能夠運行在任何遵照WSGI的Web服務器上。本文主要介紹Apache2+mod_wsgi+Django的環境搭建。所須要的軟件以下:mysql

Apache2:Web服務器
Python2.x:Python語言支持
mod_wsgi:Apache的WSGI模塊,有了該模塊的支持,就能夠用Python作爲CGI腳原本編寫網絡應用(以前還有一個 mod_python,在Apache官網上發現mod_python已通過時,漸漸要被mod_wsgi替代,聽說mod_wsig性能要好一些)
Django:一個強大的Python Web開發框架,本文的主角。
2.1 Apache的安裝nginx

下 載: http://httpd.apache.org/download.cgi  (選擇版本2.2.22,mod_wsig暫不支持2.4.2)git

解壓縮 : $tar xvfz httpd-NN.tar.gzgithub

$cd httpd-NNweb

編譯配置: $./configure –with-included-apr –prefix=PREFIX #with-included-apr選項指定使用apache軟件包裏面的apr庫

編 譯: $make

安 裝: $make install

配 置: $vim PREFIX/conf/httpd.conf

測 試: $PREFIX/bin/apachectl -k start

參 考:

官方主頁: http://httpd.apache.org/
安裝文檔: http://httpd.apache.org/docs/2.2/install.html
2.2 Python的安裝

下 載: http://www.python.org/getit/releases/2.7.3/ (選擇2.X版均可以,3.0暫不支持)

解壓縮 : $tar xvf python-X.tar

$cd python-Y

編譯配置: $./configure –enable-shared –prefix=PREFIX #–enable-shared選項指定生成python的動態庫

編 譯: $make

安 裝: $make install

測 試: $python

參 考:

官方主頁: http://www.python.org/
2.3 mod_wsgi模塊的安裝

下 載: http://code.google.com/p/modwsgi/  (選擇3.3版本)

解壓縮 : $tar xvfz mod_wsgi.X.Y.tar.gz

$cd mod_wsgi.X.Y

編譯配置: $././configure –with-apxs=/usr/local/apache2/bin/apxs –with-python=/usr/local/bin/python # 指定Apache2的模塊編譯程序和Python解析器

編 譯: $make

安 裝: $make install

測 試: $python

2.3.1  配置Apache(修改/usr/local/apche2/confi/httpd.conf)

?
1
2
3
4
5
6
7
8
9
# 加載wsgi模塊
LoadModule wsgi_module modules/mod_wsgi.so
....
# HTTP請求處理腳本
WSGIScriptAlias /test /home/xxx/www/test.wsgi
< Directory "/home/xxx/www">
Order allow, deny
Allow from all
</ Directory >

2.3.2 編寫test.wsgi(WSGI標準: http://www.python.org/dev/peps/pep-3333/

?
1
2
3
4
5
6
7
8
9
def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [( 'Content-type' , 'text/plain' ),
    ( 'Content-Length' , str ( len (output)))]
  start_response(status, response_headers)
 
  return [output]

2.3.3  重啓apche2

在任意網絡瀏覽器中輸入:http://www.mysite.com/test。看到「Hello World!」,恭喜你成功安裝了WSGI模塊。

參 考:

官方主頁: http://code.google.com/p/modwsgi/
安裝文檔: http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide
配置文檔: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide
WSGI文檔: http://www.python.org/dev/peps/pep-3333/

2.4 Django的安裝

下 載: https://www.djangoproject.com/download/  (選擇1.4版本)

解壓縮 : $tar xvfz Django-1.4.tar.gz

$cd Django-1.4

安 裝: $python setup.py install

測 試:

?
1
2
3
$python
>>> import django
>>> print (django.get_version())

參 考:

官方主頁: https://www.djangoproject.com/
安裝文檔: https://docs.djangoproject.com/en/1.4/intro/install/
快速入門: https://docs.djangoproject.com/en/1.4/intro/tutorial01/

3. Django中文支持

Django使用的是UTF-8編碼,因此對於國際化支持不成問題。由於初次玩Django,中文顯示亂,折騰死人了(一直在用的的mysql默認 字符串是latin1編碼,vim默認保存的文件編碼爲ascii)。最終得出結論,若是中文顯示亂碼,或者Django報錯(… unicode …blabla…),請檢查:

Django的設置。打開本身項目的settings.py,LANGUAGE_CODE=」zh_CN」 ?FILE_CHARSET='UTF-8′ ?DEFAULT_CHARSET='utf-8′?
查看本身項目全部的文件編碼是否以UTF-8編碼保存的?確保.py文件第一行要加上:#-*-  coding:utf-8 -*- ?
HTML模板文件head部分,添加<meta http-equiv=「Content-Type」 content=「text/html;charset=utf-8″/>
檢查本身項目的數據庫字符串編碼是否爲UTF-8,命令以下:
查看:

?
1
2
3
show create database dbname;
show create table tablename;
show full columns from tablename;

建立:

?
1
2
create database dbname CHARACTER SET utf8;
create table tblname CHARACTER SET utf8;

修改:

?
1
2
alter database dbname CHARACTER SET = utf8;
alter table tablename CONVERT TO CHARACTER SET utf8;

4. Django應用的部署

Django應用的運行有兩個方式,一種是在開發階段,使用建立項目下面的manager.py runserver ip:port來啓動一個用Python實現的輕型web服務器;另一種就是經過mod_wsgi將你本身的應用部署到生產環境,對外提供服務。下面簡 單介紹一下Django的部署(虛擬主機上的配置,自行參考文檔)。

假設你建立的Django項目文件列表以下:

?
1
2
3
4
5
6
7
8
9
10
11
my-site
|- my-site
|- myapp
  |-static
  |- ...
|- static
  |- css
  |- js
  | ...
|- apache
|- ...

4. 1. 建立Django項目的wsgi腳本(my-site/apache/django.wsgi),內容以下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import os, sys
 
sys.path.append( '/.../www/' )
sys.path.append( '/.../www/my-site' )
os.environ[ 'DJANGO_SETTINGS_MODULE' ] = 'my-site.settings'
os.environ[ 'PYTHON_EGG_CACHE' ] = '/.../www/.python-eggs'
 
import django.core.handlers.wsgi
 
_application = django.core.handlers.wsgi.WSGIHandler()
 
def application(environ, start_response):
   if environ[ 'wsgi.url_scheme' ] = = 'https' :
     environ[ 'HTTPS' ] = 'on'
   return _application(environ, start_response)

4.2. 配置Apache(httpd.conf),內容以下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 請求訪問www.xxx.com/的時候,轉到django.wsgi
WSGIScriptAlias / /.../www/my-site/apache/django.wsgi
 
<Directory /.../www/my-site/apache>
Order deny,allow
Allow from all
</Directory>
 
# 靜態文件的訪問路徑配置
Alias /static/ /.../www/my-site/static/
 
<Directory /.../www/my-site/static>
Order deny,allow
Allow from all
</Directory>

4.3. 配置setting.py

EBUG=False
自定義404.html,500.html模板(網頁未找到、服務器內部錯誤)

4.4. 靜態文件

?
1
2
3
STATIC_ROOT = ‘/…/www/my-site/static/'
STATIC_URL = ‘/static/'
$./manager.py collectstatic

注意:開發階段,通常都會把相應app的靜態文件,放在app目錄下的static目錄下。在正式生產環境部署的時候,使用./manager.py collectstatic來把全部靜態文件收集到STATIC_ROOT指定的位置,包括管理後臺的。

4.5. 重啓apahce

瀏覽器輸入相應的URL地址,看到你本身的web應用界面的話,恭喜大功告成!

5. 總結

本文主要介紹了一下Django開發環境的搭建、Django應用的部署和中文亂碼的解決方法。具體如何使用Django快速地建立本身的web應 用,並無說起。Django相對來講,文檔比較齊全,加上官方推出的一本書:《The Django Book》,相信只要開發環境搭建好,建立本身的Web應用也會很是容易。

進一步學習Django,請看:

Django1.4文檔: https://docs.djangoproject.com/en/1.4/
Django Book 英文版: http://www.djangobook.com/en/2.0/
Django Book 中文版: http://djangobook.py3k.cn/2.0/

 

 

 

 

 

 

利用Django構建web應用及其部署 

推薦兩個很是好的教程:

The Django Book(中文版):我本身一開始是參考這個教程學習的,很是有意思的是這個教程中有大量的評論,幾乎每段都有,從10年開始一直到如今。雖然這本書比較老,有不少內容都過期了,但在這些評論中有講解,有勘誤和最新的實踐,這些評論讓整個學習過程變得很是有趣。我本身也留下了很多評論,哈哈。

被解放的姜戈:這是博客園的另外一位博友Vamei(中文讀做,挖煤)寫的關於Django簡介的系列文章,基本概念,簡單的實踐都有。

 

建立一個名爲mysite的Django項目的命令:

$ django-admin startproject mysite

$ cd mysite

$ python manage.py startapp myApp  # 建立一個app,名稱爲myApp

 

一個剛建立的Django項目的目錄結構

圖1:django項目的基本結構

 

不是要點的要點


  1. 建立一個專門的用戶,例如www-data:在後面部署Django的過程當中,我遇到了自使用Linux以來,最多的權限問題。很大的緣由是由於不一樣進程間須要通訊,或相互訪問,這就須要這些用戶間都有某個文件的讀寫權限。例如兩個進程都要訪問同一個socket文件時,這兩個進程的用戶都要對該socket文件有讀寫權限。所以將全部這些進程都交給一個專門的用戶來操做,能夠避免不少權限問題。
  2. url是web開發的核心要素之一:在客戶端,每個url就是一個頁面;從開發者來看,全部的開發都是圍繞如何正確的路由這些url到正確的html文件來展開的。
  3. stackoverflow是一個很棒的網站,大部分的問題均可以在上面找到解決方案,若是沒有找到答案,就提問吧,很快就能夠獲得回覆。

 

 

概述


用戶從瀏覽器訪問一個django開發的頁面,整個流程是這樣的:

the web client <-> the web server <-> the socket <-> WSGI <-> Django

 

用戶從瀏覽器訪問一個url,該請求從用戶發送到web server,web server經過socket(或者約定一個端口)與WSGI進行通訊,再由WSGI將請求發給django。web server和WSGI都有不少種選擇,常見的組合有Apache + mod_wsgi和nginx + uWSGI。我用的是nginx + uWSGI。下面先介紹幾個名詞。

 

web server

雖然每一個網頁服務器程序有不少不一樣,但有一些共同的特色:每個網頁服務器程序都須要從網絡接受HTTP請求,而後提供HTTP回覆給請求者。HTTP回覆通常包含一個HTML文件,有時也能夠包含純文本文件、圖像或其餘類型的文件。

通常來講這些文件都存儲在網頁服務器的本地文件系統裏,而URL和本地文件名都有一個階級組織結構的,服務器會簡單的把URL對照到本地文件系統中。當正確安裝和設置好網頁服務器軟件,服務器管理員會從服務器軟件放置文件的地方指定一個本地路徑名爲根目錄。

web server是面對用戶請求的第一道門,有些請求由web server本身處理,例如靜態文件的訪問等;還有一些請求則交給WSGI處理,如對動態頁面的訪問。

 

socket: 最近在學習《計算機網絡》這門課,socket相關的內容在網絡模型中屬於傳輸層,位於網絡層和應用層之間。主要用於實現進程間通信。在這裏主要是實現nginx和uWSGI兩個不一樣進程之間的通信。

 

WSGI:

Web服務器網關接口(Python Web Server Gateway Interface,縮寫爲WSGI)是爲Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口。自從WSGI被開發出來之後,許多其它語言中也出現了相似接口。

能夠將WSGI看作是一種協議,聽說之因此Python中有不少web框架,就是由於WSGI調用很是方便。uWSGI是WSGI這一協議的實現。在實際使用過程當中,uWSGI代替了python manage.py runserver的做用,固然還有其餘做用。

最先的Web服務器只支持靜態html。隨着網站也愈來愈複雜,出現了動態技術。可是服務器並不能直接運行 php,asp這樣的文件,所以須要一個第三方,與第三方作個約定,我把請求參數發送給你,而後我接收你的處理結果給客戶端。這個約定就是 common gateway interface,簡稱cgi。這個協議能夠用vb,c,php,python 來實現。

簡單地說,cgi是Web App與Http Server之間的橋樑。

除了cgi,還有wsgi(Web Service Gateway Interface)。WSGI所在層的位置低於CGI,與CGI不一樣的是WSGI具備很強的伸縮性且能運行於多線程或多進程的環境下,這是由於WSGI只是一份標準並無定義如何去實現。實際上WSGI並不是CGI,由於其位於web應用程序與web服務器之間,而web服務器能夠是CGI。

 

 

全部均開始於settings文件


若是咱們已經建立了一個hello應用(如何建立,請參考本文開始時提到的兩個教程),而且使用下面的語句運行:

python manage.py runserver 0.0.0.0:8000

 

那麼,當咱們訪問 http://192.168.1.100:8000/hello/ 時(前面是一個局域網內的ip,8000是端口號),發生了什麼?
 
全部均開始於settings文件。當你運行python manage.py runserver,腳本將在於manage.py同一個目錄下查找名爲setting.py的文件。這個文件包含了全部有關這個Django項目的配置信息(都是大寫的變量名稱,例如 TEMPLATE_DIRS、DATABASE_NAME等)。最重要的設置是ROOT_URLCONF,它將做爲URLconf告訴Django在這個站點中哪些Python的模塊將被用到。
 
打開文件settings.py你將看到以下內容:
ROOT_URLCONF = 'mysite.urls'

 

相對應的文件是mysite/urls.py
 
當訪問URL /hello/ 時,Django根據ROOT_URLCONF的設置裝載URLconf 。而後按順序逐個匹配URLconf裏的URLpatterns,直到找到一個匹配的。當找到這個匹配的URLpatterns就調用相關聯的view函數,並把HttpRequest對象做爲第一個參數(一個視圖功能必須返回一個HttpResponse)。一旦作完,Django將完成剩餘的工做:轉換Python的對象到一個合適的帶有HTTP頭和body的Web Response(例如,網頁內容)。
 
從http requese到http response是經過下面的過程實現的:
 
訪問請求 -> setting.py -> urls.py -> views.py -> hello()
 
複製代碼
# urls.py


from django.conf.urls import url, include
from django.contrib import admin
from mysite.views import hello

admin.autodiscover()


urlpatterns = [
    url(r'^hello/$', hello),
]
複製代碼

 

複製代碼
# viwes.py

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello World!")
複製代碼

 

 

uWSGI與Django之間的通信


uWSGI與Django之間的通信是經過wsgi.py文件實現的,這個文件在建立Django project後就生成了。這裏的設置中最主要的一點就是正確的指出settings.py文件的位置。由於Django中的一切都始於這個文件。這些都使用Django的默認配置就能夠了。

複製代碼
# wsgi.py
""" WSGI config for mysite project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application # 這裏已經指定了settings文件的位置 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") application = get_wsgi_application()
複製代碼

 

一些命令:

# 安裝uwsgi

$ pip install uwsgi 

 

# 若是 python manage.py runserver 0.0.0.0:8000 能夠運行成功,則可使用下面的命令代替django自己的runserver功能(爲了可使用8000端口,須要先修改防火牆設置)

$ uwsgi --http :8000 --module mysite.wsgi  # 在項目的根目錄運行該命令(與運行python manage.py的目錄相同),參考"圖1"中的目錄結構

可是在與nginx聯合使用時,端口號由nginx中的配置決定,在uwsgi中就不用配置端口號了(因爲nginx與uwsgi之間經過socket通訊,因此直接訪問該端口號就能夠訪問整個django程序)。 

下面是一個配置文件的例子,配置完成後能夠在6001端口訪問django程序,nginx與uwsgi之間經過"/run/uwsgi/metDNA.sock"進行通訊。

複製代碼
server {
    listen                  6001;
    server_name             localhost;  # 這裏能夠根據實際狀況填寫域名或localhost
    charset                 utf-8;
    client_max_body_size    50M;

    location / {
        include     uwsgi_params;
        # include     conf.d/corsheaders.conf;
        uwsgi_pass  unix:///run/uwsgi/metDNA.sock;
    }

    # Django media
    location /media  {  # 設置www.ourlab.cn/media的具體路徑,這裏是django項目配置文件中的`MEDIA_ROOT`的位置
        # your Django project's media files - amend as required
        alias /mnt/data/metdna-upload;
    }

    location /static {  # django項目的靜態文件夾位置,即`STATIC_ROOT`的位置
        # your Django project's static files - amend as required
                # first project's static files path
        alias /mnt/data/www/metDNA/metDNA/static/static_root;
    }
}
複製代碼

 

更多詳情,能夠參考:https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html 

uwsig的配置:

  • 具體配置,能夠參考這裏
  • 由於在配置文件中設置了touch-reload參數,因此更新django代碼後,可使用 touch /path/to/wsgi.py 加載更新,而不用重啓整個django項目;
  • 使用uwsgi的emperor模式:/usr/bin/uwsgi --emperor /etc/uwsgi/sites,sites文件夾中放的是uwsgi的配置文件mysite.ini(能夠放多個django項目相關的配置文件)。該模式始終處於運行狀態,若是要中止該django項目,能夠重命名sites文件夾下對應的配置文件;

Instances under the control of the emperor should never dies.
If you want to fully stop an instance, simply remove/rename/move the instance config file in a way that the emperor rule will never match.

 

 

nginx的配置


因爲一開始不熟悉,所以nginx的配置花了很長時間。其中的關鍵點是:不一樣的server之間是沒法共用端口號(port)的,所以若是要使用同一個端口號,例如80端口,那麼全部的路由都要配置在一個server中。

  • 配置文件位置:/etc/nginx/ ;
  • 能夠將自定義的配置文件放在目錄 /etc/nginx/conf.d/,因爲在主配置文件 /etc/nginx/nginx.conf 中包含有 include /etc/nginx/conf.d/*.conf; 這條語句,因此該目錄下全部的 .conf 文件都會被加載;
  • 自定義的配置文件,能夠參考這裏nginx.conf,主要是指定端口號和server name(網站域名);

值得注意的是,上面配置文件中的sock文件,例如unix:/run/uwsgi/lipidCCS.sock,nginx的用戶和uwsgi的用戶須要同時對其進行讀寫操做,所以都須要相應的權限。靠近前端用戶的nginx和靠近後端django程序的uwsgi就是經過這個sock文件進行通訊的。

 

一些命令:

# 重啓服務:

$ sudo systemctl restart nginx.service

 

 

其餘


進程管理:進程管理的工具也有不少,uWSGI中的Emperor mode與進程管理工具具備類似的功能,二者彷佛沒法共用。我選擇的是Supervisor。

Supervisor ( http://supervisord.org) 是一個用 Python 寫的進程管理工具,能夠很方便的用來啓動、重啓、關閉進程(不只僅是 Python 進程)。除了對單個進程的控制,還能夠同時啓動、關閉多個進程,好比很不幸的服務器出問題致使全部應用程序都被殺死,此時能夠用 supervisor 同時啓動全部應用程序而不是一個一個地敲命令啓動。

uwsgi程序中的Emperor mode,會與Supervisor相互影響;Emperor mode的做用與Supervisor差很少,但本身感受Supervisor更好用一些

 
php文件:php的運行須要安裝php-fpm

 

 

重大修訂:

第一次修訂於2017年12月20日,補充了uwsgi相關配置的說明,對配置文件添加了註釋;

第二次修訂於2018年12月27日,勘誤以及修復連接(這是每一年這個時間都要寫網站的節奏啊!); 

 

參考:

https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8

https://zh.wikipedia.org/wiki/Berkeley%E5%A5%97%E6%8E%A5%E5%AD%97

https://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3

http://djangobook.py3k.cn/2.0/

http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

https://www.quora.com/What-are-the-differences-between-nginx-and-gunicorn # 這裏講了爲何要使用nginx和gunicorn(做用同uWSGI)

http://data-eater.com/python-worker/

http://www.shellwjl.com/2016/03/07/ali_flask_wsgi_Nginx/

相關文章
相關標籤/搜索