相關鏈接
Django Document
Static Files:
nginx document
uwsgi document
- Quickstart for Python/WSGI applications
- Setting up Django and your web server with uWSGI and nginx -- 強烈推薦
概念
WSGI & uwsgi
WSGI (aka Web Server Gateway Interface)是 Python 定義的標準(PEP333, PEP3333),定義了 Web Server 和 Python Web APP 之間通信的標準
uwsgi 用 C 語言實現(xiàn)了 WSGI 協(xié)議
各組件之間的關系

客戶端通過 HTTP協(xié)議 向web服務器請求網(wǎng)頁,web服務器通過 WSGI協(xié)議(或 HTTP協(xié)議,socket)與 uwsgi 通信,uwsgi 調(diào)用 Python (Django)生成動態(tài)網(wǎng)頁
為什么需要 WSGI
- 對于靜態(tài)文件(HTML, CSS, JS, image)Nginx 可以直接發(fā)布
-
但對于動態(tài)生成的網(wǎng)頁,Nginx 需要通過 WSGI 向 Django 獲??;
nginx 需要服務兩種內(nèi)容
部署
所需組件
- Django 項目
- uwsgi
- nginx
Django 項目
# mysite/settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目的根目錄
MEDIA_DIR = os.path.join(BASE_DIR, 'media') # 存放 Media 的目錄
DEBUG = True
INSTALLED_APPS = [
'rango',
# ...
'django.contrib.staticfiles',
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# Static File
STATIC_URL = '/static/'
# Media File
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'
為 Media Files 聲明 URL
# mysite/urls.py
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path
urlpatterns = [
# ...
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
$ python manage.py runserver


在開發(fā)階段,Django runserver 會通過
django.contrib.staticfiles自動服務位于 app 目錄下的 Static 文件和指定目錄 Media 文件
nginx
systemctl status nginx # 查看狀態(tài)
systemctl start nginx.service # 啟動 nginx
systemctl enable nginx.service # 開機啟動 nginx

nginx 配置文件
在 Django 項目根目錄下創(chuàng)建 nginx 配置文件:mysite_nginx.conf
下面以一個項目為例:
- 項目根目錄:
/root/django_projects/rango_website/ - static 文件目錄:
/www/rango_website/static - media 文件目錄:
/www/rango_website/media
# mysite_nginx.conf
# the upstream component nginx needs to connect to
# nginx 與 uwsgi 通信的地址
upstream django-rango {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8002; # for a web port socket (we'll use this first)
}
# 配置一臺 Web Server, 監(jiān)聽 8080 端口
# configuration of the server
server {
# the port your site will be served on
listen 8080;
# the domain name it will serve for
server_name demo.econfig.cn; # substitute your machine's IP address or FQDN # web Server ip地址或域名
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# 指向 Media Files 目錄
# Django media
location /media {
alias /www/rango_website/media; # your Django project's media files - amend as required
}
# 指向 Static Files 目錄
location /static {
alias /www/rango_website/static; # your Django project's static files - amend as required
}
# 指向 Django 項目
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django-rango; # 上面 upstream 定義的名字
include /root/django_projects/rango_website/uwsgi_params; # the uwsgi_params file you installed
}
}
將 nginx 目錄下的 uwsgi_params 復制到 Django項目根目錄
$ cp /etc/nginx/uwsgi_params ~/django_projects/rango_website/
創(chuàng)建鏈接文件:將 Django項目根目錄(上面剛剛創(chuàng)建)的 mysite_nginx.conf 鏈接到 nginx 的配置目錄
$ sudo ln -s django_projects/rango_website/django-rango.conf /etc/nginx/conf.d/
讓 nginx 重新載入配置文件
$ nginx -s reload
將 static文件 和 media文件 放到上面指定的目錄
# mysite/settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_DIR = '/www/rango_website/static' # static 要存放的目錄
# 現(xiàn)在不用告訴 Django : media file 在哪里,因為它交給 nginx 處理
# 但如果還要 運行 Django runserver ,則可以保留
# MEDIA_DIR = os.path.join(BASE_DIR, 'media')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ['demo.econfig.cn']
# Application definition
INSTALLED_APPS = [
'rango',
# ...
'django.contrib.staticfiles',
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# django 用于生成 static 文件的鏈接
STATIC_URL = '/static/'
STATIC_ROOT = STATIC_DIR
# 現(xiàn)在不用告訴 Django : media文件 在哪里
# 因為 static文件和 media文件 交給 nginx 去發(fā)布
# 但如果還要 運行 Django runserver ,則可以保留
MEDIA_URL = '/media/'
# MEDIA_ROOT = MEDIA_DIR
將 Django 項目 所有app的 static 文件收集到 /www/rango_website/static
$ python manage.py collectstatic

手動復制 media 文件
$ cp -r ./media /www/rango_website/
給 static 文件 和 media 文件訪問權限
# chmod -R 755 /www
哎,終于好了,static 文件和 media 文件都交給 nginx 發(fā)布;人在塔在

但首頁卻無法訪問,因為動態(tài)頁面要由 Django 生成,而我們還沒啟用 uwsgi

uwsgi :nginx 和 django 之間的通信媒介
注:這里的 djagno 項目是事先在 pipenv 虛擬環(huán)境創(chuàng)建的
$ pipenv install uwsgi # 安裝uwsgi
$ pipenv shell # 進入 pipenv 虛擬環(huán)境
創(chuàng)建 uwsgi 配置文件:mysite_uwsgi.ini
[uwsgi]
socket = :8002 # uswgi 端口
chdir = /root/django_projects/rango_website # django項目根目錄
module = rango_website.wsgi # django項目的 wsgi 模塊 rango_website/wsgi.py
processes = 4 # 工作進程數(shù)
threads = 2 # 線程數(shù)
stats = 127.0.0.1:9002 # 進程統(tǒng)計信息
virtualenv = /root/.local/share/virtualenvs/rango_website-e68KS5mW/ # 虛擬環(huán)境位置
# 1個 uwsgi 主進程
# 4個 處理請求的進程
# 每個工作進程有2個線程
啊?我忘記虛擬環(huán)境的路徑是什么了...
$ pipenv --venv # 查看虛擬環(huán)境路徑
/root/.local/share/virtualenvs/rango_website-e68KS5mW
啟動 uswgi
$ uwsgi rango_uwsgi.ini





錯誤
訪問 static 文件和 media 文件 出現(xiàn) 404 錯誤
反問三連
- nginx 配置文件中 static 文件和 media文件 的路徑正確嗎

重新載入 nginx 配置文件了嗎
nginx -s reloadstatic 文件 和 media 文件放到 指定目錄了嗎
$ python manage.py collectstatic
$ cp -r ./media /www/rango_website/
訪問 static 文件和 media 文件 出現(xiàn) 403 錯誤 (拒絕訪問)
目錄權限給了嗎 # chmod -R 755 /www
