Django 1.6 最佳实践: 如何设置django项目的设置(settings.py)和部署文件(requirements.txt)
Django 1.6 最佳实践: 如何设置django项目的设置(settings.py)和部署文件(requirements.txt)
在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"),
)
Django 1.6 最佳实践: 如何设置django项目的设置(settings.py)和部署文件(requirements.txt)的更多相关文章
- django 强制登录最佳实践
参考: https://python-programming.courses/recipes/django-require-authentication-pages/ 即通过中间件来做AOP拦截.不用 ...
- Django REST Framework 最佳实践
Django REST framework 是一个强大且灵活的工具包,用以构建Web APIs. 为什么要使用REST framework? - 在线可视的API,对于赢得你的开发者们十分有用 - 验 ...
- Celery学习--- Celery 最佳实践之与django结合实现异步任务
django 可以轻松跟celery结合实现异步任务,只需简单配置即可 同步执行和异步执行 注意:即使Celery的任务没有执行完成,但是已经创建了任务ID.可以利用前台的定时任务发送Ajax异步请求 ...
- Kubernetes 服务部署最佳实践(一) ——如何更好地设置 Request 与 Limit
如何为容器配置 Request 与 Limit? 这是一个即常见又棘手的问题,这个根据服务类型,需求与场景的不同而不同,没有固定的答案,这里结合生产经验总结了一些最佳实践,可以作为参考. 所有容器都应 ...
- django项目的配置文件settings.py详解
我们创建好了一个Python项目(mysite/)之后,需要在项目中添加模块应用(polls/),在模块应用中添加处理功能逻辑,如添加模块中的视图处理函数(polls.views.index()),这 ...
- Django 项目拆分配置文件settings.py
使用Django命令生成一个项目的基本结构时, 配置信息默认保存在和项目目录同名的目录下的settings.py文件里, 对于一个项目而言, 这样往往是不合适的, 在实际的开发中,需要将配置文件拆分为 ...
- Django 1.6 最佳实践: 如何设置和使用 Log(转)
原文: http://www.weiguda.com/blog/37/ 任何参与过高要求的大型项目的编程人员都明白设置适当的log等级, 创建不同的logger, 记录重要事件的重要性. 正确的设置和 ...
- Django 1.6 最佳实践: 如何正确使用 Signal(转)
原文:http://www.weiguda.com/blog/38/ 如何正确的使用signal: 简单回答是: 在其他方法无法使用的情况下, 才最后考虑使用signal. 因为新的django开发人 ...
- Django 1.6 最佳实践: django项目的服务器自动化部署(转)
原文:http://www.weiguda.com/blog/41/ 当我们设置服务器时, 不应该每次都使用ssh登录服务器, 再按照记忆一步一步的配置. 因为这样实在是太容易忘记某些步骤了. 服务器 ...
随机推荐
- Yii系列教程(二):功能简介
1 MVC架构 1.1处理流程 一个Web请求在Yii内部的执行流程如下图所示: 1.2组件角色 组件名 角色与责任 index.php 入口脚本.创建Application的单例对象. applic ...
- 字符串中符号的替换---replace的用法
#include<iostream> #include<string> using namespace std; int main() { string s1 = " ...
- delphi 中 image 控件加载bmp、JPG、GIF、PNG等图片的办法
procedure TForm1.Button1Click(Sender: TObject);var jpg: TJPEGImage; // 要use Jpeg单元begin // 显示jpg大图 ...
- Drupal如何更新注册表?
Drupal的注册表是指registry和registry_file两个数据表.前一个表保存所有可用的类和接口以及它们所对应的文件,后一个表保存每个文件的hash码. 1. 将所有需要更新的文件都汇总 ...
- 通知(Toast+Notification)
Toast简要说明:(前面已经用过好多次了) Toast是一种非持久的(在屏幕上面留一会儿就消失了),提供给用户简洁提示信息的视图. 它不阻断用户的操作,一般用于显示一些不重要的信息.(比方说设置音量 ...
- fopen警告处理方式
warning C4996: “fopen”被声明为否决的 问题:vs2005中编程时,遇到如下: warning C4996: “fopen”被声明为否决的. 解释:微软的警告,主要是那些都是C库的 ...
- Http状态码的种类及含义
1xx 临时响应:2xx 成功:3xx 重定向: 4xx 请求错误: 5xx 服务器错误: http://www.hostspaces.net/wenzhang-detail.php?id=198 常 ...
- Android中使用logwrapper来重定向应用程序的标准输出
在Android应用程序调试中,有时候第三方应用程序的日志输出是通过printf之类的标准函数输出的,logcat不能捕获这些日志,一个方法是使用logwrapper命令来执行第三方应用程序,logw ...
- Java Web高性能开发(二)
今日要闻: 性价比是个骗局: 对某个产品学上三五天个把月,然后就要花最少的钱买最多最好的东西占最大的便宜. 感谢万能的互联网,他顺利得手,顺便享受了智商上的无上满足以及居高临下的优越感--你们一千块买 ...
- 使用VMware10虚拟机安装Linux系统(能力工场)
作为IT从业人员,我们经常使用到Linux系统,但是实际开发过程我们通常在Windows平台操作,为了满足工作需要,这个时候我们通常在windows平台安装虚拟机,并在其上建立linux系统,这样就极 ...