关于python:如何配置Django进行简单的开发和部署?

How do you configure Django for simple development and deployment?

我在做Django的时候经常用sqlite开发,但在实时服务器上,更强大的功能是经常需要(例如mysql/postgresql)。总是有其他的变化要对姜戈设置:不同的日志记录位置/强度,媒体路径等。

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


更新:Django配置已经发布,这对于大多数人来说可能是一个更好的选择,而不是手工操作。

如果您愿意手动操作,我之前的回答仍然适用:

我有多个设置文件。

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

我把这些都和一个settings.py文件联系在一起,该文件首先导入settings_local.py,然后再导入另外两个文件中的一个。它通过settings_local.pyDEVELOPMENT_HOSTSPRODUCTION_HOSTS中的两个设置来决定加载哪个。settings.py调用platform.node()来查找正在运行的机器的主机名,然后在列表中查找该主机名,并根据找到主机名的列表加载第二个设置文件。

这样一来,您真正需要担心的是保持settings_local.py文件与主机特定的配置保持最新,其他一切都将自动处理。

在这里查看一个示例。


就我个人而言,我在项目中使用了single settings.py,我只是让它查找它所使用的主机名(我的开发机器有以"gabriel"开头的主机名,所以我有:

1
2
3
4
5
import socket
if socket.gethostname().startswith('gabriel'):
    LIVEHOST = False
else:
    LIVEHOST = True

在其他方面,我也有这样的事情:

1
2
3
4
5
6
7
8
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/'

等等。可读性稍差一点,但它工作得很好,省去了处理多个设置文件的麻烦。


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

1
2
3
4
try:
    from settings_local import *
except ImportError:
    pass

这样,如果我想覆盖默认设置,我只需要将settings_local.py放在settings.py旁边。


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


我发现最简单的方法是:

1)使用默认设置.py进行本地开发和2)创建production-settings.py开始于:

1
2
import os
from settings import *

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

1
2
3
4
5
6
7
8
9
DEBUG = False
TEMPLATE_DEBUG = DEBUG


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

有点相关,对于将django本身部署到多个数据库中的问题,您可能需要查看djangostack。您可以下载一个完全免费的安装程序,它允许您安装Apache、python、django等。作为安装过程的一部分,我们允许您选择要使用的数据库(mysql、sqlite、postgresql)。我们在内部自动化部署时广泛使用安装程序(它们可以在无人值守模式下运行)。


好吧,我使用这个配置:

在settings.py的末尾:

1
2
3
4
5
#settings.py
try:
    from locale_settings import *
except ImportError:
    pass

在locale_settings.py中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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

我的settings.py文件在一个外部目录中。这样,它就不会签入源代码管理,也不会被部署重写。我把它和任何默认设置放在我的django项目下的settings.py文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
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_settings.py,这是非常危险的。


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

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

所以在移动项目时,我只需要编辑这些设置,而不需要搜索整个文件。

我还建议查看Fabric和Capistrano(Ruby工具,但它可以用于部署Django应用程序),这有助于远程部署的自动化。


这是一个旧的帖子,但我认为如果我添加这个有用的library,它将简化事情。

使用Django配置

快速启动

1
pip install django-configurations

然后在项目的settings.py或任何其他用于存储设置常量的模块中对包含的configuration s.configuration类进行子类划分,例如:

1
2
3
4
5
6
# mysite/settings.py

from configurations import Configuration

class Dev(Configuration):
    DEBUG = True

DJANGO_CONFIGURATION环境变量设置为刚才创建的类的名称,例如在~/.bashrc中:

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能够使用您的配置,您现在必须修改manage.py或wsgi.py脚本,以使用django配置的相应启动程序函数版本,例如使用django配置的典型manage.py如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
#!/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文件,例如:

1
2
3
4
5
6
7
8
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函数。

就是这样!现在,您可以将项目与manage.py和您最喜爱的支持wsgi的服务器一起使用。


这么多复杂的答案!

每个settings.py文件都附带:

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

我使用该目录设置这样的调试变量(使用dev代码所在的directoy获取):

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

然后,每次移动settings.py文件时,debug都将为false,这是您的生产环境。

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

1
2
3
4
if(DEBUG):
    #Debug setting
else:
    #Release setting


我使用环境:

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

我相信这是一种更好的方法,因为最终您需要为您的测试环境进行特殊的设置,并且您可以很容易地将其添加到这个条件中。


我认为这取决于站点的大小,以及您是否需要从使用sqlite开始,我已经在几个较小的活动站点上成功地使用了sqlite,并且运行良好。


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

所以为了自动化您的部署并消除这些WOMM问题,只需使用Docker。