Django 1.6 最佳實踐: 如何設置django項目的設置(settings.py)和部署文件(requirements.txt)


Django 1.6 最佳實踐: 如何設置django項目的設置(settings.py)和部署文件(requirements.txt)

 

作者: Desmond Chen, 發布日期: 2014-05-17, 修改日期: 2014-05-18

在Django 1.6中的settings.py中可以修改130多項設置, 但大多數都繼承自默認值. 設置是在web服務器啟動時首次載入的, 服務器重啟時重新載入, 因此, 程序員們應盡量避免修改正式服務器上使用的settings.py文件. 以下是一些我們應當遵循的原則:

  • 所有的設置文件應當進行版本管理
  • 不要重復自己 (don't repeat yourself)
  • 妥善保存關鍵信息

之前, 我們采用的方法是, 不將設置文件放入git庫中, 每個開發人員本地有一份自己的設置文件. 但我們發現這樣做是錯誤的. 因為:

  • 在debug之前, 我們可能已經花費了大量精力去模擬正式服務器上出現的錯誤, 但最終發現這是由於正式服務器的settings文件設置和本地不同而 出現的問題. 這時你的心情會是怎樣?
  • 當你在開發django項目時, 發現並修復了一個bug. 當將這一commit push到服務器后, 你突然發現這一bug的出現完全是因為你修改了本地的 settings文件而產生的, 而由於你的push, 又導致了服務器的宕機. 這時你又會是怎樣的感受?
  • 每個人都會從另一個程序員那里拷貝/黏貼settings文件內容, 這難道不是違反了"不要重復自己"的原則嗎?

正式由於這些問題, 所以我們現在采用不一樣的設置方式. 我們首先建立一個基本的設置文件, 然后將開發和正式部署的設置文件分離成不同的模塊, 但 這些模塊都繼承自同一個基本設置文件:

1. 使用分離式的設置文件

django項目建立時, 會自動生成settings.py文件. 為了實現分離式的設置文件, 我們首先刪除settings.py, 然后建立settings目錄:

    settings/ __init__.py base.py local.py test.py production.py ...
設置文件 目的
base.py 基本設置文件, 在各個環境中都相同的設置可以放入其中.
local.py 當在開發時使用的設置文件. 可以設置開發時的選項, 包括DEBUG, log的等級, 是否開啟例如 django-debug-toolbar等開發工具等.
test.py 運行test時的配置, 包括test runners, in-memory數據庫定義和log設置等.
production.py 當部署到正式服務器上所用的設置.

我們可以使用以下命令使用這些不同的設置文件:

    python manage.py shell --settings=mysite.settings.local python manage.py runserver --settings=mysite.settings.local

當然如果你熟悉 DJANGO_SETTINGS_MODULE 和 PYTHONPATH 的話, 也可以事先設置好 DJANGO_SETTINGS_MODULE 和 PYTHONPATH 環境變量, 這樣做的好處就是你不必使用--settings了.

如果你對virtualenv有深入的了解的話, 也可以在postactivate腳本中設置 DJANGO_SETTINGS_MODULE 和 PYTHONPATH.

local.py的例子

    # settings/local.py from .base import * DEBUG = True TEMPLATE_DEBUG = DEBUG EMAIL_BACKEND = 'django.core.email.backends.console.EmailBackend' DATABASES = { "defaults": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "weiguda", "USER": "", "PASSWORD": "", "HOST": "localhost", "PORT": "", } } INSTALLED_APPS += ("debug_toolbar",)

有時, 一個開發人員的配置文件可能與另一個不同, 這時, 我們可以在settings目錄中新建local_name.py:

    # settings/local_name.py from .local import * # 設置不同的配置 CACHE_TIMEOUT = 30

2. 將關鍵信息和設置文件分離

將SECTET_KEY, AWS key文件, API key文件等關鍵信息放入設置文件中也是違反基本原則的. 因為:

  • 配置環境不同時關鍵信息會改變, 程序卻不會.
  • 關鍵信息不是程序.
  • 關鍵信息應當是隱蔽的, 如果儲存在了版本管理系統中, 則任何有權訪問該版本庫的用戶都能獲知這些關鍵信息.
  • 許多PAAS服務無法為每台服務器編輯設置文件, 即使可以, 這也是不正確的做法.

環境變量

為了避免以上的問題, 我們使用環境變量 (environment variables) 來儲存這些關鍵信息, (需要注意的是, apache不支持環境變量, 我們會在下面講到). 使用環境變量儲存關鍵信息有以下好處:

  • 將關鍵信息從代碼中移除, 這樣你就可以安心的將所有文件放入版本管理系統中.
  • 每個開發人員都擁有一樣的local.py文件.
  • 在部署django項目時, 不需要修改程序代碼.
  • 大多數PAAS都推薦這一方法, 並提供了方便的設置方法, 因此容易實現.
設置環境變量

在使用bash的Mac或Linux中設置環境變量比較容易, 你只需要將以下代碼加入.bashrc, .bash_profile, 或.profile其中之一即可. 如果多個項目 使用相同的API, 並且關鍵信息都不同時, 可以將以下代碼加入到virtualenv的bin/activate腳本中:

    $ export SOME_SECRET_KEY=654-3jgwg-4r3-2t4h-76jk $ export ANOTHER_SECRET_KEY=y5y-5jk8-75i5h-5g4/.-,o.

如果使用的是windows系統, 則設置稍微復雜一點. 如果使用cmd.exe, 你必須使用setx命令一個一個的設置, 一個較好的方式是使用virtualenv的 bin/activate.bat

    > setx OME_SECRET_KEY=654-3jgwg-4r3-2t4h-76jk

PowerShell是Windows Vista及以上自帶的shell, 它比cmd.exe強大得多. 因此可以使用PowerShell來設置環境變量:

    # 為用戶User設置 [Environment]::SetEnvironmentVariable("SOME_SECRET_KEY", "654-3jgwg-4r3-2t4h-76jk", "User") # 為全局設置 [Environment]::SetEnvironmentVariable("SOME_SECRET_KEY", "654-3jgwg-4r3-2t4h-76jk", "Machine")

如果你使用virtuanenvwrapper, 那么可以使用virtualenvwrapper的pre-virtualenv設置環境變量, 這樣可能會更方便.

如果你使用PAAS, 則請參閱不同的PAAS提供的設置方法.

獲取環境變量

在設置好環境變量后, 我們來看如何在django的settings代碼中獲取這些關鍵信息:

    # 在settings/production.py頂部 import os SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]

在以上代碼中, 如果SOME_SECRET_KEY無法被獲取到的話, 就會出現KeyError錯誤, 導致django項目無法啟動. 這很好, 但KeyError沒有提供更有 用的信息, 導致debug的困難, 因此, 我們在base.py(希望你還記得這是哪個文件)加入以下function, 為我們提供哪個關鍵信息無法獲取的信息:

    # settings/base.py import os # 通常你不應該從django引入任何代碼, 但ImproperlyConfigured是個例外 from django.core.exceptions import ImproperlyConfigured def get_env_variable(var_name): try: return os.environ[var_name] except KeyError: error_msg = "Set the %s environment variable" % var_name raise ImproperlyConfigured('error_msg')

然后修改之前的production.py:

    # 在settings/production.py頂部 import os SOME_SECRET_KEY = get_env_variable('SOME_SECRET_KEY')

此時, 當你沒有設置SOME_SECRET_KEY環境變量時, 系統會提示錯誤信息, 告訴你是哪個環境變量沒有設置.

無法使用環境變量時

當我們使用apache時, 我們會發現, django無法使用環境變量. 這時, 我們推薦將關鍵信息儲存在JSON格式的文件中, 已達到將關鍵信息和代碼分離的 目的. 首先我們可以創建secrets.json文件:

    { "FILENAME": "secrets.json", "SOME_SECRET_KEY": "654-3jgwg-4r3-2t4h-76jk" }

在settings中使用該文件:

    # settings/base.py import json # 通常你不應該從django引入任何代碼, 但ImproperlyConfigured是個例外 from django.core.exceptions import ImproperlyConfigured # 讀取json文件 with open("secrets.json") as f: secrets = json.loads(f.read()) def get_secret(setting, secrets=secrets): try: return secrets[setting] except KeyError: error_msg = "Set the {0} environment variable".format(setting) raise ImproperlyConfigured('error_msg') SOME_SECRET_KEY = get_secret('SOME_SECRET_KEY')

3. 使用不同的部署文件(requirements.txt)

部署文件(requirements.txt)中儲存的是該django項目的依賴庫, 一般使用pip freeze --local生成. 本着"只安裝需要的模塊"的原則, 不同的設 置文件, 應當對應不同的requirements.txt文件. 就像分離式的settings文件一樣, 我們使用分離式的requirements文件. 首先我們刪除前文中提到的repository_root中的requirements.txt, 然后建立requirements目錄:

    requirements/ base.txt local.txt production.txt

在base.txt中, 儲存的是所有開發環境中都會用到的依賴庫, 例如:

    Django==1.6.5 psycopg2==2.5.3 South==0.8.4

在local.txt中, 儲存的是本地開發時用到的依賴庫:

    # 導入base.txt中的依賴庫 -r base.txt coverage==3.7.1 django-debug-toolbar==1.2

當重新配置本地開發環境時, 可以使用以下代碼安裝依賴庫:

    pip install -r requirements/local.txt

4. 設置文件中的文件路徑

我們強烈反對將絕對路徑寫入設置文件中, 因為如果將絕對路徑寫入設置文件中的話, 遇到不同的環境, 就需要重新修改, 給開發和部署帶來了許多麻煩 和不確定性.

我們推薦使用Unipath來設置media, static和templates的 路徑. 這樣無論部署測試環境如何變化, media和templates文件夾的設置都不會有問題.

    # settings/base.py 頂部 from unipath import Path BASE_DIR = Path(__file__).ancestor(3) MEDIA_ROOT = BASE_DIR.child("media") STAIC_ROOT = BASE_DIR.child("static") TEMPLATES_DIRS = ( BASE_DIR.child("templates"), )

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM