为本地开发和生产服务器处理设置的推荐方法是什么?其中一些(如常量等)可以在两者中更改/访问,但其中一些(如静态文件的路径)需要保持不同,因此不应该在每次部署新代码时都重写。

目前,我正在将所有常量添加到settings.py中。但是每次我在本地更改一些常量时,我都必须将其复制到生产服务器并编辑文件以进行特定于生产的更改……:(

编辑:看起来这个问题没有标准答案,我已经接受了最流行的方法。


当前回答

不要使用settings.py,而是使用下面的布局:

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

py是您的大部分配置所在的位置。

py从common中导入所有内容,并覆盖它需要覆盖的内容:

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

类似地,dev.py从common.py导入所有内容,并覆盖它需要覆盖的内容。

最后,__init__.py是你决定加载哪些设置的地方,也是你存储秘密的地方(因此这个文件不应该被版本化):

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### DJANGO SECRETS
SECRET_KEY = '(3gd6shenud@&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

我喜欢这个解决方案的原因是:

所有东西都在您的版本控制系统中,除了机密信息 大多数配置都在一个地方:common.py。 特定于产品的东西放在prod。py中,特定于开发的东西放在dev。py中。这很简单。 你可以在prod.py或dev.py中覆盖common.py中的内容,也可以覆盖__init__.py中的任何内容。 这是简单的python。没有重新导入黑客。

其他回答

我在django split-settings的帮助下管理我的配置。

它是默认设置的临时替换。它很简单,但可配置。并且不需要重构现有设置。

下面是一个小例子(文件示例/settings/__init__.py):

from split_settings.tools import optional, include
import os

if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
    include(
        'components/default.py',
        'components/database.py',
        # This file may be missing:
        optional('local_settings.py'),

        scope=globals()
    )

就是这样。

更新

我写了一篇关于用django-split-sttings管理django设置的博文。看看吧!

我对这个问题的解决方案在某种程度上也是这里已经提到的一些解决方案的混合:

我保留了一个名为local_settings.py的文件,其内容为USING_LOCAL = True在dev中,USING_LOCAL = False在prod中 在settings.py中,我对该文件进行导入以获得USING_LOCAL设置

然后我将所有与环境相关的设置都基于此:

DEBUG = USING_LOCAL
if USING_LOCAL:
    # dev database settings
else:
    # prod database settings

我更喜欢这样,而不是有两个单独的settings.py文件,我需要维护,因为我可以将我的设置结构化地保存在一个文件中,而不是将它们分布在几个文件中。就像这样,当我更新一个设置时,我不会忘记在两个环境中都这样做。

当然每种方法都有它的缺点,这种方法也不例外。这里的问题是,无论何时将更改推到生产环境中,我都不能覆盖local_settings.py文件,这意味着我不能盲目地复制所有文件,但这是我可以接受的。

我认为最好的解决方案是@T提出的。但是我不知道为什么在Django中不使用DEBUG标志。我写下面的代码为我的网站:

if DEBUG:
    from .local_settings import *

简单的解决方案总是比复杂的解决方案好。

如果你愿意,可以选择维护不同的文件: 如果您正在使用git或任何其他VCS将代码从本地推送到服务器,您可以将设置文件添加到.gitignore。

这将允许您在两个地方有不同的内容而没有任何问题。所以在服务器上,你可以配置一个独立版本的settings.py,任何在本地所做的更改都不会反映在服务器上,反之亦然。

此外,它将删除settings.py文件从github也,大错误,这我已经看到许多新手做。

我在manage.py中区分它,并创建了两个单独的设置文件:local_settings.py和prod_settings.py。

在manage.py中检查服务器是本地服务器还是生产服务器。如果它是本地服务器,它将加载local_settings.py,如果它是生产服务器,它将加载prod_settings.py。基本上是这样的:

#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager 

ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
    try:
        import local_settings # Assumed to be in the same directory.
        settings = local_settings
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)
else:
    try:
        import prod_settings # Assumed to be in the same directory.
        settings = prod_settings    
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

if __name__ == "__main__":
    execute_manager(settings)

我发现将设置文件分开到两个单独的文件中更容易,而不是在设置文件中做大量的if。