Two Scoops Django 推荐的 Settings 和 Requirements 文件设置
基本原则
Django 1.8 有约 140 个配置项可通过 settings 模块进行设置。settings 模块在每次启动 Django 服务时进行初始化,因此对 settings.py 文件修改后,都要重启 Django 服务器才能生效。
所有 settings 文件都应进行版本控制,包括对配置项的修改日期/时间和注释信息进行版本控制
DRY,通过
import base_settings
进行继承,避免复制粘贴机密信息不要放在版本控制中
使用多个 settings 文件
settings/__init__.pybase.pylocal.pystaging.pytest.pyproduction.py
并且每个 settings 文件都对应有一个 requirements 文件
settings 文件名 | 目的
-----------------------|
local.py, dev.py | 本地开发环境配置内容,如 DEBUG=True
, 开启 django-debug-toolbar 等
staging.py | 针对 Staging 阶段的配置内容
test.py | 针对运行测试的配置内容
production.py, prod.py | 生产环境下的配置内容
ci.py | 针对持续集成服务器的配置内容
使用方法:
- shell 中
python manage.py shell --settings=twoscoops.settings.local
- 启动服务
python manage.py runserver --settings=twoscoops.settings.local
- 设置 DJANGO_SETTINGS_MODULE 和 PYTHONPATH 环境变量。若使用了 virtualenv,可以在每个环境的激活脚本中设置 DJANGO_SETTINGS_MODULE 和 PYTHONPATH。
一个开发环境中的 settings 文件的例子:
# settings/local.py
from .base import *DEBUG = TrueEMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'DATABASES = {"default": {"ENGINE": "django.db.backends.postgresql_psycopg2","NAME": "twoscoops","USER": "","PASSWORD": "","HOST": "localhost","PORT": "",}
}INSTALLED_APPS += ("debug_toolbar", )
上面的例子中有 from .base import *
, 这是 import *
在 Django 中唯一被赞成使用的地方。因为我们想在 settings 文件中覆盖所有的命名空间。
针对开发环境也可以有多个 settings 文件
基本原则是每个 settings 文件都需要版本控制。可针对不同的开发者创建相应的 settings 文件,如:
# settings/dev_pydanny.py
from .dev import *# Set short cache timeout
CACHE_TIMEOUT = 30
而创建后的所有 settings 文件会是:
settings/__init__.pybase.pydev.pydev_audreyr.pydev_pydanny.pylocal.pystaging.pytest.pyproduction.py
将配置信息从代码中分离出来
将 SECRET_KEY、API KEY 等信息存放在代码库中有以下问题:
这些信息针对每次部署都要变动
SECRET_KEY 等值是配置值,不是代码
存放在代码库中,有代码库访问权限的人都能看到
多数 PaaS 不提供针对单台服务器的配置功能
解决方案是使用 环境变量。
使用环境变量来存放 SECRET_KEY 等信息的好处:
由于这些敏感信息已保存它处,你会毫不犹豫地对每个文件进行版本控制
针对每次部署,不再需要对这些配置信息进行修改
多数 PaaS 平台推荐使用环境变量,并提供了相应的配置和管理工具
如何在本地进行环境变量设置
在 Linux/Mac 的 bash 中,通过将配置代码添加到 .bashrc、.bash_profile 或 .profile 等文件后面进行配置。若使用 virtualenv,也可以在 virtualenv 的 bin/activate 脚本中添加配置代码进行配置:
配置代码:
$ export SOME_SECRET_KEY=1c3-cr3am-15-yummy$ export AUDREY_FREEZER_KEY=y34h-r1ght-d0nt-t0uch-my-1c3-cr34m
在 Win 上,可以在 cmd.exe 中通过 setx 命令进行配置,也可以在 virtualenv 的 bin/activate.bat 脚本中进行配置。
配置代码:
> set SOME_SECRET_KEY 1c3-cr3am-15-yummy
PowerShell 比 cmd.exe 更加强大,在 Vista 及以上版本中可用。使用 PowerShell 进行环境变量设置:
只针对当前用户:
[Environment]::SetEnvironmentVariable("SOME_SECRET_KEY","1c3-cr3am-15-yummy", "User")
[Environment]::SetEnvironmentVariable("AUDREY_FREEZER_KEY","y34h-r1ght-d0nt-t0uch-my-1c3-cr34m", "User")
针对本机的全部用户:
[Environment]::SetEnvironmentVariable("SOME_SECRET_KEY","1c3-cr3am-15-yummy", "Machine")
[Environment]::SetEnvironmentVariable("AUDREY_FREEZER_KEY","y34h-r1ght-d0nt-t0uch-my-1c3-cr34m", "Machine")
生产环境中的环境变量配置举例
- 在 Heroku 上配置
$ heroku config:set SOME_SECRET_KEY=1c3-cr3am-15-yummy
- 在 Python 中存取这些配置信息
>>> import os
>>> os.environ["SOME_SECRET_KEY"]
"1c3-cr3am-15-yummy"
- 在 settings 文件中存取这些配置信息
# Top of settings/production.py
import os
SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]
对未设置 SECRET_KEY 的异常进行处理
如果没有 SECRET_KEY 值, 上面的存取代码会抛出 KeyError,项目也无法启动。但是该异常没有提供有效的提示信息,不利于调试。
在 settings/base.py 中使用以下代码进行处理:
# settings/base.py
import os# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigureddef get_env_variable(var_name):"""Get the environment variable or return exception."""try:return os.environ[var_name]except KeyError:error_msg = "Set the {} environment variable".format(var_name)raise ImproperlyConfigured(error_msg)
然后在 settings 文件中,使用:
SOME_SECRET_KEY = get_env_variable("SOME_SECRET_KEY")
之后,如果没有设置 SOME_SECRET_KEY 这个环境变量,会出现以下的错误提示:
django.core.exceptions.ImproperlyConfigured: Set the SOME_SECRET_KEY
environment variable.
manage.py
会默认将 DJANGO_SETTINGS_MODULE 指向 settings.py,推荐在多 settings 文件时使用 django-admin
,而单 settings 文件时使用 manage.py
, 这两个命令基本是等同的:
$ django-admin <command> [options]
$ manage.py <command> [options]
当不能设置环境变量时
Apache 等使用自己的环境变量,如以上的针对系统的环境变量设置方法无效,此时可以将敏感信息保存在一个不可执行的文件中,并且不对该文件进行版本控制:
为保存敏感信息生成一个文件,格式可以为 JSON、Config、YAML 或 XML。
增加一个 loader 来对这些信息进行管理
将该文件名增加到 .gitignore 和 .hgignore
使用 JSON 格式
- 生成 secrets.json 文件:
{"FILENAME": "secrets.json","SECRET_KEY": "I've got a secret!","DATABASES_HOST": "127.0.0.1","PORT": "5432"
}
- 在 settings/base.py 中添加 loader,来存取这些信息:
# settings/base.pyimport json# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured# JSON-based secrets module
with open("secrets.json") as f:secrets = json.loads(f.read())def get_secret(setting, secrets=secrets):"""Get the secret variable or return explicit exception."""try:return secrets[setting]except KeyError:error_msg = "Set the {0} environment variable".format(setting)raise ImproperlyConfigured(error_msg)SECRET_KEY = get_secret("SECRET_KEY")
使用多个 requirements 文件
每个 settings 文件需对应有一个 requirements 文件,并且对应不同的配置,只安装相应的依赖文件。
requirements 文件举例:
requirements/base.txtlocal.txtstaging.txtproduction.txt
base.txt 中存放全局依赖,如:
Django==1.8.0
psycopg2==2.6
djangorestframework==3.1.1
而针对本地开发环境的 local.txt,可以在 base.txt 的基础上添加其它依赖:
-r base.txt # includes the base.txt requirements filecoverage==3.7.1
django-debug-toolbar==1.3.0
对于持续集成服务器的 ci.txt 可以是:
-r base.txt # includes the base.txt requirements filecoverage==3.7.1
django-jenkins==0.16.4
而 production.txt 基本会和 base.txt 相同,可能会是:
-r base.txt # includes the base.txt requirements file
安装
针对本地开发:
$ pip install -r requirements/local.txt
针对生产环境:
$ pip install -r requirements/production.txt
所有 requirements 文件中的依赖包都指定为特定的一个版本,这样能确保项目更加稳定。
在 settings 文件中处理文件路径
不要对文件路径进行硬编码
- 使用 Unipath 进行文件路径处理
# At the top of settings/base.py
from unipath import PathBASE_DIR = Path(__file__).ancestor(3)
MEDIA_ROOT = BASE_DIR.child("media")
STATIC_ROOT = BASE_DIR.child("static")
STATICFILES_DIRS = (BASE_DIR.child("assets"),
)
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates',DIRS = (BASE_DIR.child("templates"),)},
]
- 使用 os.path 进行文件路径处理
# At the top of settings/base.py
from os.path import join, abspath, dirnamehere = lambda *dirs: join(abspath(dirname(__file__)), *dirs)
BASE_DIR = here("..", "..")
root = lambda *dirs: join(abspath(BASE_DIR), *dirs)# Configuring MEDIA_ROOT
MEDIA_ROOT = root("media")# Configuring STATIC_ROOT
STATIC_ROOT = root("collected_static")# Additional locations of static files
STATICFILES_DIRS = (root("assets"),
)# Configuring TEMPLATE_DIRS
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates',DIRS = (root("templates"),)},
]
要找到你的配置文件与 Django 默认配置的区别,使用 Django 的 diffsettings
命令。
参考文献: Two Scoops of Django: Best Practices for Django 1.8
Two Scoops Django 推荐的 Settings 和 Requirements 文件设置相关推荐
- Two Scoops Django 推荐的数据模型最佳实践
添加或修改数据模型都不能马虎,有关数据的操作都需慎重考虑. 推荐使用的 Django 数据模型相关的包: django-model-utils: 使用其 TimeStampedModel django ...
- python打不开settings_python - django无法导入settings文件
python - django无法导入settings文件 小葫芦2017-04-17 13:48:34 0 3 133 Traceback (most recent call last): ...
- Django学习之十: staticfile 静态文件
目录 Django学习之十: staticfile 静态文件 理解阐述 静态文件 Django对静态文件的处理 其它方面 总结 Django学习之十: staticfile 静态文件 理解阐述 静态文 ...
- django mysql 时区_django 中的时区设置
在settings.py中设置了 TIME_ZONE = 'Asia/Shanghai' USE_TZ = True 现在的北京时间是 22点35分.django shell 中运行 timezone ...
- Django中载入js和css文件
Django中载入js和css文件 项目的文件夹结构例如以下: mysite |-mysite |-|-static |-|---js和css文件 |-|-|-init.py |-| |-models ...
- Python之web开发(二):python使用django框架搭建网站之新建文件
本文为Django项目创建的简单介绍,更为详细的Django项目创建,编辑可以参考http://www.imooc.com/learn/790 Step 1. 点击 File --> New P ...
- django中FastDFS客户端与自定义文件存储系统
什么是FastDFS FastDFS 是用 c 语言编写的一款开源的分布式文件系统.FastDFS 为互联网量身定制, 充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用 ...
- 推荐一个实用的 .gitignore 文件
转载自 推荐一个实用的 .gitignore 文件 为什么要忽略文件? 常用的版本控制工具,不管是使用 git 还是 svn,我们都需要排除一些与程序代码无关的文件,如像 eclipse/ in ...
- django源码阅读 manage.py文件
Django源码阅读之manager.py文件阅读 我们知道,我们运行一个django项目的时候,需要进入项目的根目录,然后输入命令,python manage.py runserver,这样,我们就 ...
最新文章
- c语言智能指针是什么,C ++中的智能指针
- 基于python的界面自动化测试-基于Python语言的自动化测试实战第二章(上)
- yii mysql 缓存_yii2优化 - 开启 Schema 缓存
- (计算机组成原理)第二章数据的表示和运算-第三节3:浮点数加减运算
- 不会SQL注入,连漫画都看不懂了
- 手rm-linux联网后自动dhcp,Linux操作系统下DHCP简单设置
- itext设置字体间距_汉语拼音的字体到底选哪个?你是不是一直很困扰?来看总结方法...
- 塔防游戏制作教程(一)
- 表示背景色彩的html是,[html颜色代码]HTML语言中,设置背景颜色的代码是?
- 来自GitHub的Python开源项目,100%可用的12306多功能抢票助手,切勿作为商业用途
- 键盘按钮KeyCode使用案例
- php doctrine,PHP和Doctrine:如何创建唯一ID
- dump文件 修复iat_手动修复IAT
- bert-textcnn实现多标签文本分类(基于keras+keras-bert构建)
- python实现微信群友统计器
- oracle索引一般叫什么意思,什么是oracle索引?
- 杰克 - 鬼马海盗主角加勒比海盗系列的
- [开源精品] C#.NET im 聊天通讯架构设计 -- FreeIM 支持集群、职责分明、高性能
- 【图像重建】基于布雷格曼迭代(bregman alteration)算法集合ART算法实现CT图像重建附matlab代码
- lynda怎样免费看_您可能可以从本地图书馆获得免费的Lynda.com访问
热门文章
- HTML关于机器猫的小游戏,完美起航-用HTML5+CSS3画一个简易的机器猫头像
- 探讨安防行业产学研发展现状及问题
- 解决insmod igb_uio.ko报错问题
- zynq操作系统:Linux打实时补丁preempt_rt
- http 400报错
- 微信电子健康卡操作类
- 红帽企业版RHEL7.1在研域工控板上,开机没有登陆窗口 -- 编写xorg.conf 简单三行解决Ubuntu分辩率不可调的问题...
- 机会网络(DTN)——MaxProp
- python数据转换成pdf_python使用reportlab转换jpg为pdf
- 成为安全架构师需要了解什么