如何为简单的开发和部署配置 Django?

我倾向于在做 Django 时使用 SQLite 但是在实时服务器上,更健壮的是 经常需要(例如,MySQL/PostgreSQL)。 不可避免地,还需要对 Django 进行其他更改 设置: 不同的日志位置/强度, 媒体路径等。

如何管理所有这些更改以使部署成为 简单的自动化程序?

26110 次浏览

更新: Django-构型已经发布了,对大多数人来说,这可能是一个比手动操作更好的选择。

如果你更喜欢手动操作,我之前的答案仍然适用:

我有多个设置文件。

  • settings_local.py-特定于主机的配置,例如数据库名称、文件路径等。
  • settings_development.py-用于开发的配置,例如 DEBUG = True
  • settings_production.py-用于生产的配置,例如 SERVER_EMAIL

我将所有这些与一个 settings.py文件绑定在一起,该文件首先导入 settings_local.py,然后导入另外两个文件中的一个。它通过 settings_local.py-DEVELOPMENT_HOSTSPRODUCTION_HOSTS中的两个设置来决定加载哪个。settings.py调用 platform.node()来查找它正在运行的机器的主机名,然后在列表中查找该主机名,并加载第二个设置文件,具体取决于它在哪个列表中查找主机名。

这样,您真正需要担心的唯一事情就是使 settings_local.py文件与主机特定的配置保持最新,并且其他所有事情都会自动处理。

查看一个例子 给你

我有两份文件。settings_base.py,它包含通用/默认设置,并且已签入源代码管理。每个部署都有一个单独的 settings.py,它在开始时执行 from settings_base import *,然后根据需要重写。

除了 Jim 提到的多个设置文件之外,我还倾向于在我的 setings.py 文件中放入两个设置,分别设置在 BASE_DIRBASE_URL的顶部,设置为代码的路径和网站的基址,所有其他的设置都被修改为附加到这些设置中。

BASE_DIR = "/home/sean/myapp/" 例如 MEDIA_ROOT = "%smedia/" % BASEDIR

因此,当移动项目,我只需要编辑这些设置,而不是搜索整个文件。

我还建议看一下结构和 Capistrano(Ruby 工具,但它可以用来部署 Django 应用程序) ,它们可以促进远程部署的自动化。

就我个人而言,我在项目中使用一个 setings.py,我只是让它查找它所在的主机名(我的开发机器的主机名都是以“ gabriel”开头的,所以我只有这个:

import socket
if socket.gethostname().startswith('gabriel'):
LIVEHOST = False
else:
LIVEHOST = True

然后在其他部分,我有这样的东西:

if LIVEHOST:
DEBUG = False
PREPEND_WWW = True
MEDIA_URL = 'http://static1.grsites.com/'
else:
DEBUG = True
PREPEND_WWW = False
MEDIA_URL = 'http://localhost:8000/static/'

可读性稍差,但工作正常,省去了处理多个设置文件的麻烦。

在 setings.py 的末尾,我有以下内容:

try:
from settings_local import *
except ImportError:
pass

这样,如果我想覆盖默认设置,我只需要把 set _ local.py 放在 setings.py 旁边。

我认为这取决于站点的大小,至于你是否需要从使用 SQLite 提高,我已经成功地在几个较小的站点上使用 SQLite,它运行得很好。

我将 setings.py 文件放在一个外部目录中。这样,它就不会被签入源代码管理,或者被部署覆盖。我把它放在 Django 项目的 setings.py 文件中,以及任何默认设置:

import sys
import os.path


def _load_settings(path):
print "Loading configuration from %s" % (path)
if os.path.exists(path):
settings = {}
# execfile can't modify globals directly, so we will load them manually
execfile(path, globals(), settings)
for setting in settings:
globals()[setting] = settings[setting]


_load_settings("/usr/local/conf/local_settings.py")

注意: 如果不能信任 local _ setings.py,那么这是非常危险的

我发现的最简单的方法是:

1)使用默认的 设置进行本地开发; 2) create a Production-settings.py starting with:

import os
from settings import *

然后覆盖生产中不同的设置:

DEBUG = False
TEMPLATE_DEBUG = DEBUG




DATABASES = {
'default': {
....
}
}

对于使用多个数据库部署 Django 本身的问题,可能需要查看一下 姜戈斯塔克。您可以下载一个完全免费的安装程序,它允许您安装 Apache、 Python、 Django 等。作为安装过程的一部分,我们允许您选择要使用的数据库(MySQL、 SQLite、 PostgreSQL)。在内部自动化部署时(可以在无人参与模式下运行) ,我们广泛使用安装程序。

我用这个配置:

在 setings.py 的末尾:

#settings.py
try:
from locale_settings import *
except ImportError:
pass

在 locale _ sets.py 中:

#locale_settings.py
class Settings(object):


def __init__(self):
import settings
self.settings = settings


def __getattr__(self, name):
return getattr(self.settings, name)


settings = Settings()


INSTALLED_APPS = settings.INSTALLED_APPS + (
'gunicorn',)


# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings

我使用环境:

if os.environ.get('WEB_MODE', None) == 'production' :
from settings_production import *
else :
from settings_dev import *

I believe this is a much better approach, because eventually you need special settings for your test environment, and you can easily add it to this condition.

事实上,您可能应该考虑为您的开发和生产环境使用相同(或几乎相同)的配置。否则,像“嘿,它在我的机器上工作”这样的情况就会时不时地发生。

因此,为了自动化部署并消除 WOMM 问题,只需使用 多克

这么多复杂的答案!

每个 setings.py 文件都附带:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

我使用这个目录来设置 DEBUG 变量,如下所示(用开发代码所在的 directoy 重新替换) :

DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
DEBUG = True

然后,每次移动 setings.py 文件时,DEBUG 将为 False,这是您的生产环境。

每次您需要与开发环境中的设置不同的设置时,只需使用:

if(DEBUG):
#Debug setting
else:
#Release setting

这是一个较老的职位,但我认为,如果我添加这个有用的 library将简化事情。

使用 Django 配置

快速启动

pip install django-configurations

然后对包含的配置进行子类化。在项目的 setings.py 或任何其他用于存储设置常量的模块中的配置类,例如:

# mysite/settings.py


from configurations import Configuration


class Dev(Configuration):
DEBUG = True

将环境变量设置为你刚刚创建的类的名称,例如:

export DJANGO_CONFIGURATION=Dev

以及 DJANGO_SETTINGS_MODULE会像往常一样环境变量到模块导入路径,例如,在 bash 中:

export DJANGO_SETTINGS_MODULE=mysite.settings

或者 在沿着 Django 的默认 --settings命令行选项使用 Django 管理命令时提供 --configuration选项,例如:

python manage.py runserver --settings=mysite.settings --configuration=Dev

为了使 Django 能够使用你的配置,你现在必须修改你的 经理人 Py或者 Wsgi.py脚本来使用 Django-configuration 版本的适当的启动函数,例如一个典型的使用 Django-configuration 的 经理人 Py应该是这样的:

#!/usr/bin/env python


import os
import sys


if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')


from configurations.management import execute_from_command_line


execute_from_command_line(sys.argv)

注意,在第10行中,我们没有使用通用工具 django.core.management.execute_from_command_line,而是使用了 configurations.management.execute_from_command_line

这同样适用于 wsgi.py文件,例如:

import os


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')


from configurations.wsgi import get_wsgi_application


application = get_wsgi_application()

这里我们不使用默认的 django.core.wsgi.get_wsgi_application函数,而是使用 configurations.wsgi.get_wsgi_application函数。

就是这样! 您现在可以使用 经理人 Py和您最喜欢的启用了 WSGI 的服务器的项目。

为什么要把事情搞得这么复杂?我是从 PHP/Laravel 背景进入 Django 的。我使用 .env,您可以轻松地配置它。

安装此包

django-environ

现在,在 settings.py所在的文件夹中,创建一个文件 .env(确保将该文件放在 gitignore 中)

.env文件中,放置 env 变量,如调试设置状态、密钥、邮件凭据等 示例 .env的快照

SECRET_KEY="django-insecure-zy%)s5$=aql=#ox54lzfjyyx!&uv1-q0kp^54p(^251&_df75i"


DB_NAME=bugfree
DB_USER=postgres
DB_PASSWORD=koushik
DB_PORT=5433
DB_HOST=localhost


APP_DEBUG=True # everything is string here

在设置中,确保使用

import environ
env = environ.Env()
environ.Env.read_env()

现在您可以从 .env文件中导入值,并将它们放在任何您想要的位置

SECRET_KEY = env('SECRET_KEY')
DEBUG = bool(env('APP_DEBUG', False))

You can also put default value too like this

env('DB_NAME', 'default value here')

小费 您可以在同一个文件夹中创建另一个 .env.example,其中您有 .env文件,您可以有一个 .env模板,您可以提交 .example文件。它可以帮助未来的开发人员很容易地知道 env 变量是什么。 .env.example would be something like this

SECRET_KEY=VALUE_HERE


DB_NAME=VALUE_HERE
DB_USER=VALUE_HERE
DB_PASSWORD=VALUE_HERE
DB_PORT=VALUE_HERE
DB_HOST=VALUE_HERE


EMAIL_HOST=VALUE_HERE
EMAIL_PORT=VALUE_HERE
EMAIL_HOST_USER=VALUE_HERE
EMAIL_HOST_PASSWORD=VALUE_HERE
DEFAULT_FROM_EMAIL=VALUE_HERE