django+uwsgi+nginx 前後端分離部署配置
本文僅用於記錄自己的踩坑過程,避免以後有同樣需求的時候沒思路
開發環境
後端部分
- django==3.2.8
- sqlite3==3.36.0
前端部分
- vue==2.6.14
- elementui (版本不知道)
- axios (版本不知道)
伺服器環境
- uwsgi==2.0.20
- nginx==1.20.1
所有的程式碼檔案都位於 /myweb
目錄下,該目錄的結構如下:
這裡的/myweb/backend/daily_exercise/exercise
資料夾是使用 djangoadmin startproject
時自動建立的,/myweb/backend/daily_exercise/daily
目錄則是使用 python manage.py startapp
後端部分位於
/myweb/backend/daily_exercise
,前端部分位於/myweb/frontend/daily_exercise
後端使用 uwsgi 進行部署,加上 nginx 進行轉發以避免跨站問題,前端只用 nginx 部署。
後端部署:uwsgi 部署 django
先安裝 uwsgi
pip install uwsgi
然後在任意地方建立一個 uwsgi 的配置檔案。本例中叫 uwsgi.ini,位於 /myweb/backend/
目錄下,雖然 /myweb/backend/daily_exercise/
目錄下還有一個同名的 uwsgi.ini,但是在伺服器端部署用不到這個檔案,這個檔案是在本地部署時候用到的,因為在伺服器上的 /myweb/backend/daily_exercise/
/myweb/backend/uwsgi.ini
檔案內容如下
[uwsgi] http=:8000 master=True processes=4 threads=4 chdir=/myweb/backend/daily_exercise wsgi-file=/myweb/backend/daily_exercise/exercise/wsgi.py vacuum=True max-requests=5000 daemonize=/var/log/uwsgi/daily_exercise.log pidfile=/tmp/daily_exercise.pid py-autoreload=1
其中,要注意的是以下幾個引數:
- http 表示程式將要執行在哪個埠。本例是 8000
- chdir 是 django 專案的根目錄地址,也就是 manage.py 檔案所在的目錄
- wsgi-file 是專案中 wsgi.py 檔案地址。這裡可以寫成是相對地址,也可以是絕對地址
- daemonize 指明 django 專案執行時產生的日誌檔案位置
- pidfile 指定 django 專案執行時將要產生的程序檔名稱和位置
- py-autoreload 指定是否自動過載。如果等於 1,則在程式碼更新後,uwsgi 服務會自動過載。否則需要手動過載(命令是:uwsgi --reload /tmp/daily_exercise.pid)
然後執行:
uwsgi uwsgi.ini
即可部署完畢。可以檢視 /var/log/uwsgi/daily_exercise.log
的內容,檢查是否有報錯,如果沒有報錯就沒問題。同時也可以直接開啟 http://伺服器id:8000 (或其它在 django 中定義的有效路徑)來觀察部署結果。
前端部署:nginx 部署純前端專案
如果系統中沒有安裝 nginx,需要先安裝,網上有很多教程。
安裝完後,修改 /etc/nginx/nginx.conf 配置檔案
http {
server {
localhost /frontend/daily {
alias /myweb/frontend/daily_exercise;
}
}
}
如上,在預設的 http > server 內加入以下三行即可。
localhost /frontend/daily {
alias /myweb/frontend/daily_exercise;
}
其中 localhost
後面的 /frontend/daily
是自定義的訪問地址,訪問時在伺服器地址後面加上這個自定義地址即可,如:http://伺服器IP/frontend/daily
至此,前端、後端分別部署完畢。但是由於 django 部署使用的是 8000 埠,前端部署使用的是預設的 80 埠,前端發請求時會有跨站(CROS)問題。
比如,前端需要向後端介面 http://localhost:8000/daily/api 發請求獲取資料,則在前端會出現跨站請求的錯誤。
一個解決的思路是,前端只向預設的 80 埠發請求,由 nginx 轉發到 8000 埠,就不會有這個問題。
配置 nginx 解決跨站問題
同樣簡單,在前述的 nginx 配置檔案 /etc/nginx/nginx.conf
檔案中加上轉發的規則,同樣是在 http -> server 下新增:
locahost /daily/api {
proxy_pass http://127.0.0.1:8000/daily/api;
proxy_redirect default;
}
這樣,當在瀏覽器中開啟 http://伺服器IP/daily/api
時,nginx 會轉發至 http://127.0.0.1:8000/daily/api
這個地址。
當然以上是硬編碼的方式,並不是最優解,網上還有其它方式可以更加靈活地實現這種不同埠之間的轉發。
別忘了修改 django 專案中的跨站訪問配置
需要安裝 django 的 cros 外掛:
pip install django-cros-headers
修改 /myweb/backend/daily_exercise/exercise/settings.py
檔案,新增以下內容
CORS_ORIGIN_WHITELIST = (
'http://127.0.0.1:8000',
'http://localhost:8000',
'http://localhost',
'http://127.0.0.1',
)
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'POST',
'PUT',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
再修改同文件下的MIDDLEWARE
變數,增加corsheaders.middleware.CorsMiddleware
允許跨站(CROS問題解決)後,在前端程式碼中可以使用相對路徑來訪問後端的介面(這樣可以在沒有配置 nginx 轉發的本地環境中也能正常執行),例如:
解決 sqlite3 版本過低的問題
在本地(或伺服器)使用 python manage.py runserver
時,如果 sqlite3 版本過低,專案是執行不起來的,會 sqlite3 版本過低的錯誤,因為 django3 要求 sqlite3 的版本要大於等於 3.9.0,可以先按網上的教程升級系統的 sqlite3
sqlite 官網中提供的最新版本應該是遠高於 3.9 的。
升級完後,使用 python manage.py runserver
命令執行應該沒問題了,但是使用 uwsgi 部署時,很可能依然還會報版本過低的錯誤,如下,可在uwsgi.ini檔案內指定的/var/log/uwsgi/daily_exercise.log
檔案中看到錯誤:
估計是程式找不到最新安裝的 sqlite3,原因不明,也未找到解決辦法,按網上說的新增引數到 bash_profile 無效,使用引數重新編譯 python 也沒有作用。
最終我是直接修改 django 中的判斷語句來避開這個檢測的。如上圖中的黃色框部分,修改這個檔案裡面的check_sqlite_version
函式,如下:
上圖是修改後的,修改前黃框中應該是(3, 9, 0)
至此,問題解決,部署完畢!
(本文完)--------------------------------------------------------------------------------------------------------------------------
致虛極,守靜篤
使用我的阿里雲幸運券,購買阿里雲ECS有優惠:阿里雲幸運券
>>>>> 騰訊雲新使用者優惠 <<<<<