在生產中提供檔案

weixin_34116110發表於2018-03-01

Django本身不提供檔案; 它將該作業留給您選擇的任何Web伺服器。 我們建議使用單獨的Web伺服器 - 即不是也在執行Django的伺服器 - 用於服務媒體。 以下是一些不錯的選擇:

  • Nginx
  • 精簡版的Apache

但是,如果您沒有選擇,只能在與Django相同的Apache VirtualHost上提供媒體檔案,則可以將Apache設定為將某些URL作為靜態媒體提供,而將其他裝置用於使用Django的mod_wsgi介面。

此示例在站點根目錄中設定Django,但將/ robots.txt,favicon.ico,任何CSS檔案以及/ static /和/ media / URL空間中的任何內容顯式地作為靜態檔案提供。 所有其他URL將使用mod_wsgi提供:

Alias /robots.txt /path/to/mysite.com/static/robots.txt
Alias /favicon.ico /path/to/mysite.com/static/favicon.ico

Alias /media/ /path/to/mysite.com/media/
Alias /static/ /path/to/mysite.com/static/

<Directory /path/to/mysite.com/static>
Require all granted
</Directory>

<Directory /path/to/mysite.com/media>
Require all granted
</Directory>

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

如果您使用的是2.4以前版本的Apache,請將Require all granted替換為Allow from all,並且新增 line Order deny,允許在其之上。

提供管理檔案

當django.contrib.staticfiles在INSTALLED_APPS中時,Django開發伺服器會自動提供管理應用程式的靜態檔案(以及其他已安裝的應用程式)。 然而,當您使用任何其他伺服器配置時,情況並非如此。 您負責設定Apache或您使用的任何Web伺服器來為管理檔案提供服務。

管理檔案位於Django發行版的(django / contrib / admin / static / admin)中。 我們強烈建議使用django.contrib.staticfiles來處理管理檔案(以及上一節中概述的Web伺服器;這意味著使用collectstatic management命令來收集STATIC_ROOT中的靜態檔案,然後配置您的Web伺服器以進行服務 STATIC_URL在STATIC_URL),但這裡有三種其他方法:

  1. 從文件根目錄中建立一個到管理靜態檔案的符號連結(這可能需要在Apache配置中新增+ FollowSymLinks)。

  2. 如上所示,使用Alias指令將相應的URL(可能是STATIC_URL + admin /)別名到管理檔案的實際位置。

  3. 複製管理靜態檔案,以便它們位於Apache文件根目錄中。

如果你得到一個Unicodeencodeerror

如果您正在利用Django的國際化功能,並且您打算允許使用者上傳檔案,則必須確保用於啟動Apache的環境已配置為接受非ASCII檔名。 如果您的環境未正確配置,則在呼叫包含非ASCII字元的檔名的os.path中的函式時,將觸發UnicodeEncodeError異常。

為了避免這些問題,用於啟動Apache的環境應包含類似於以下內容的設定:

export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'

請參閱您作業系統的文件以獲取適當的語法和位置以放置這些配置項; / etc / apache2 / envvars是Unix平臺上的常見位置。 一旦將這些語句新增到您的環境中,請重新啟動Apache。

在生產中提供靜態檔案

將靜態檔案投入生產的基本概述很簡單:在靜態檔案更改時執行collectstatic命令,然後將收集的靜態檔案目錄(STATIC_ROOT)安排到靜態檔案伺服器並提供服務。

根據STATICFILES_STORAGE,可能需要手動將檔案移動到新的位置,否則Storage類的post_process方法可能會處理此問題。

當然,就像所有部署任務一樣,惡魔在細節上。 每個生產設定都會有所不同,因此您需要調整基本輪廓以適應您的需求。

以下是一些可能有所幫助的常見模式。

從同一伺服器提供站點和您的靜態檔案

如果您想從已經為您的網站提供服務的同一伺服器提供靜態檔案,則此過程可能如下所示:

  • 將程式碼推送到部署伺服器。
  • 在伺服器上執行collectstatic將所有靜態檔案複製到STATIC_ROOT。
  • 配置您的Web伺服器以在STATIC_URL下的STATIC_ROOT中提供檔案。

您可能希望自動執行此過程,特別是如果您擁有多個Web伺服器。 有許多方法可以實現這種自動化,但許多Django開發人員喜歡Fabric的一種選擇。

在下面和下面的章節中,我們將展示幾個自動執行這些檔案部署選項的fabfiles(即Fabric指令碼)示例。 fabfile的語法非常簡單,但不會在這裡介紹; 請參閱Fabric的文件,以獲取語法的完整說明。 因此,將靜態檔案部署到幾個Web伺服器的fabfile可能如下所示:

from fabric.api import *

# Hosts to deploy onto
env.hosts = ['www1.example.com', 'www2.example.com']

# Where your project code lives on the server
env.project_root = '/home/www/myproject'

def deploy_static():
    with cd(env.project_root):
        run('./manage.py collectstatic -v0 --noinput')
從專用伺服器提供靜態檔案

大多數較大的Django站點使用單獨的Web伺服器(即,不是也在執行Django的伺服器)來提供靜態檔案。 該伺服器通常執行不同型別的Web伺服器 - 速度更快但功能更少。 一些常見的選擇是:

  • Nginx
  • 精簡版的Apache

配置這些伺服器超出了本文件的範圍; 檢查每個伺服器的正確文件以獲取指示。 由於您的靜態檔案伺服器不會執行Django,因此您需要修改部署策略,如下所示:

  1. 當您的靜態檔案更改時,請在本地執行collectstatic。
  2. 將您的本地STATIC_ROOT到靜態檔案伺服器推送到正在提供服務的目錄中。 rsync是此步驟的常用選擇,因為它只需傳輸已更改的靜態檔案的位。
    下面是在fabfile中可能的外觀:
from fabric.api import *
 from fabric.contrib import project

 # Where the static files get collected locally. Your STATIC_ROOT setting.
 env.local_static_root = '/tmp/static'

 # Where the static files should go remotely
 env.remote_static_root = '/home/www/static.example.com'

 @roles('static')
 def deploy_static():
     local('./manage.py collectstatic')
     project.rsync_project(
         remote_dir = env.remote_static_root,
         local_dir = env.local_static_root,
         delete = True
     )
從雲服務或CDN提供靜態檔案

另一種常見策略是從Amazon S3和/或CDN(內容交付網路)等雲端儲存提供商處提供靜態檔案。 這可以讓您忽略服務靜態檔案的問題,並且通常可以使網頁更快載入(特別是在使用CDN時)。

在使用這些服務時,基本工作流看起來有點像上面的,除了使用rsync將靜態檔案傳輸到伺服器之外,您需要將靜態檔案傳輸到儲存提供程式或CDN。 有多種方式可以做到這一點,但如果提供者具有API,則自定義檔案儲存後端將使該過程變得非常簡單。

如果您已經編寫或正在使用第三方自定義儲存後端,則可以通過將STATICFILES_STORAGE設定為儲存引擎來告訴collectstatic使用它。 例如,如果您在myproject.storage.S3Storage中編寫了S3儲存後端
你可以使用它:

STATICFILES_STORAGE = 'myproject.storage.S3Storage'

完成之後,您只需執行collectstatic,並將靜態檔案通過儲存包推送到S3。 如果以後需要切換到不同的儲存提供商,則可以像更改STATICFILES_STORAGE設定一樣簡單。 有第三方應用程式可用於為許多常見的檔案儲存API提供儲存後端。 djangopackages.com提供了一個很好的起點。

相關文章