如何在Django中管理本地和生产设置?

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

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

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

122392 次浏览

记住,settings.py是一个活动代码文件。假设您没有在生产中设置DEBUG(这是一个最佳实践),您可以执行如下操作:

if DEBUG:
STATIC_PATH = /path/to/dev/files
else:
STATIC_PATH = /path/to/production/files

非常基本,但是理论上,您可以根据DEBUG的值或您想使用的任何其他变量或代码检查来提高任何复杂级别。

我使用settings_local.py和settings_production.py。在尝试了几个选项后,我发现当简单地拥有两个设置文件时,很容易在复杂的解决方案上浪费时间。

当你在Django项目中使用mod_python/mod_wsgi时,你需要将它指向你的设置文件。如果你把它指向本地服务器上的app/settings_local.py和生产服务器上的app/settings_production.py,那么事情就变得简单了。只需编辑适当的设置文件并重新启动服务器(Django开发服务器将自动重新启动)。

我使用Harper Shelby发布的“if DEBUG”风格设置的稍微修改版本。显然,根据环境(win/linux/等等),代码可能需要稍作调整。

我在过去使用“if DEBUG”,但我发现偶尔我需要用DEUBG设置为False进行测试。我真正想要区分的是环境是生产环境还是开发环境,这给了我选择DEBUG级别的自由。

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
PRODUCTION = True
else:
PRODUCTION = False


DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG


# ...


if PRODUCTION:
DATABASE_HOST = '192.168.1.1'
else:
DATABASE_HOST = 'localhost'

我仍然认为这种设置方式是一种正在进行中的工作。我还没有看到任何一种方法来处理Django设置,它涵盖了所有的基础,同时设置起来也不是很麻烦(我不喜欢5x设置文件方法)。

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

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

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

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

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

当然每种方法都有它的缺点,这种方法也不例外。这里的问题是,我不能覆盖local_settings.py文件每当我把我的更改推向生产,这意味着我不能只是盲目地复制所有文件,但这是我可以忍受的。

settings.py:

try:
from local_settings import *
except ImportError as e:
pass

你可以覆盖local_settings.py;它应该不在你的版本控制范围之内。但既然你提到了复制,我猜你没有使用;)

我在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。

对于我的大多数项目,我使用以下模式:

  1. 创建settings_base.py,其中存储所有环境的通用设置
  2. 每当我需要使用具有特定要求的新环境时,我都会创建新的设置文件(例如。settings_local.py),它继承settings_base.py的内容并覆盖/添加适当的设置变量(from settings_base import *)

(要使用自定义设置文件运行manage.py,只需使用——settings命令选项:manage.py <command> --settings=settings_you_wish_to_use.py)

我使用了上面提到的jpartogi的一个变体,我觉得它更简短:

import platform
from django.core.management import execute_manager


computername = platform.node()


try:
settings = __import__(computername + '_settings')
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file '%r_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" % (computername, __file__))
sys.exit(1)


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

基本上,在每台计算机(开发或生产)上,我都有适当的动态加载的hostname_settings.py文件。

大多数这些解决方案的问题是,你要么有你的本地设置应用之前常用的,要么他们。

所以不可能覆盖

  • 特定于env的设置定义了memcached池的地址,在主设置文件中,这个值用于配置缓存后端
  • 特定环境的设置添加或删除应用程序/中间件到默认的

同时。

一种解决方案可以使用“ini”风格的配置文件和ConfigParser类实现。它支持多个文件、延迟字符串插值、默认值和许多其他优点。 一旦加载了一些文件,可以加载更多的文件,它们的值将覆盖之前的文件(如果有的话)

您可以加载一个或多个配置文件,这取决于计算机地址、环境变量,甚至是先前加载的配置文件中的值。然后只需使用解析后的值填充设置。

我成功使用的一个策略是:

  • 加载一个默认的defaults.ini文件
  • 检查机器名,并加载所有与反向FQDN匹配的文件,从最短匹配到最长匹配(因此,我加载了net.ini,然后是net.domain.ini,然后是net.domain.webserver01.ini,每一个都可能覆盖前一个的值)。这个帐户也适用于开发人员的机器,因此每个人都可以为本地开发设置自己首选的数据库驱动程序等
  • 检查是否声明了“集群名称”,在这种情况下加载cluster.cluster_name.ini,它可以定义数据库和缓存ip等内容

举个例子,你可以定义一个“子域”值per-env,然后在默认设置中使用(作为hostname: %(subdomain).whatever.net)来定义django工作所需的所有必要的主机名和cookie。

这是我能得到的DRY,大多数(现有的)文件只有3或4个设置。除此之外,我还必须管理客户配置,所以存在一组额外的配置文件(包括数据库名称、用户和密码、分配的子域等),每个客户一个或多个。

您可以根据需要将其扩展到低或高,只需在配置文件中放入您想要在每个环境中配置的键,一旦需要新的配置,将先前的值放在默认配置中,并在必要时覆盖它。

该系统已被证明是可靠的,并与版本控制工作良好。它已经被使用很长时间来管理两个独立的应用程序集群(每台机器上有15个或更多的django站点实例),有超过50个客户,集群的大小和成员会根据系统管理员的情绪而变化……

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

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

common.py是你的大部分配置所在的位置。

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

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


# Production overrides
DEBUG = False
#...

类似地,dev.pycommon.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..."

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

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

Django 1.5的最佳实践建议对设置文件使用版本控制,并将文件存储在单独的目录中:

project/
app1/
app2/
project/
__init__.py
settings/
__init__.py
base.py
local.py
production.py
manage.py

base.py文件包含常见设置(例如MEDIA_ROOT或ADMIN),而local.pyproduction.py有特定于站点的设置:

在基文件settings/base.py中:

INSTALLED_APPS = (
# common apps...
)

在本地开发设置文件settings/local.py中:

from project.settings.base import *


DEBUG = True
INSTALLED_APPS += (
'debug_toolbar', # and other apps for local development
)

在文件生产设置文件settings/production.py中:

from project.settings.base import *


DEBUG = False
INSTALLED_APPS += (
# other apps for production site
)

然后当你运行django时,你添加--settings选项:

# Running django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local


# Running django shell on the production site
$ ./manage.py shell --settings=project.settings.production

这本书的作者还在Github上发布了一个示例项目布局模板

我发现这里的回答很有帮助。(这个问题是否得到了更明确的解决?上一次回复是在一年前。)在考虑了列出的所有方法之后,我提出了一个在这里没有列出的解决方案。

我的标准是:

  • 一切应该在源代码控制中。我不喜欢精细的东西到处乱放。
  • 理想情况下,将设置保存在一个文件中。如果我不看东西,我就会忘记它们:)
  • 无需部署手动编辑。应该能够用一个fabric命令测试/推送/部署。
  • 避免将开发设置泄漏到生产环境中。
  • 让Django布局尽可能接近“标准”(*咳嗽*)。

我认为在主机上切换是有意义的,但后来发现真正的问题是不同的环境的不同设置,并有一个啊哈时刻。我把这段代码放在我的settings.py文件的结束中:

try:
os.environ['DJANGO_DEVELOPMENT_SERVER'] # throws error if unset
DEBUG = True
TEMPLATE_DEBUG = True
# This is naive but possible. Could also redeclare full app set to control ordering.
# Note that it requires a list rather than the generated tuple.
INSTALLED_APPS.extend([
'debug_toolbar',
'django_nose',
])
# Production database settings, alternate static/media paths, etc...
except KeyError:
print 'DJANGO_DEVELOPMENT_SERVER environment var not set; using production settings'

这样,应用程序违约到生产设置,这意味着你显式地“白名单”你的开发环境。忘记在本地设置环境变量要比反过来忘记在生产环境中设置一些内容而使用一些开发设置安全得多。

在本地开发时,无论是在shell中,还是在.bash_profile中,或者其他任何地方:

$ export DJANGO_DEVELOPMENT_SERVER=yep

(或者如果你在Windows上开发,可以通过控制面板或者其他什么工具来设置…Windows总是让它变得如此模糊,以至于你可以设置环境变量。)

使用这种方法,开发设置都在一个(标准)位置,只需在需要的地方覆盖生产设置。任何与开发设置有关的事情都应该完全安全地提交到源代码控制中,而不会对生产产生影响。

我也在与Laravel合作,我喜欢那里的实现。我试着模仿它,并将其与T. Stone提出的解决方案结合起来(见上文):

PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]


def check_env():
for item in PRODUCTION_SERVERS:
match = re.match(r"(^." + item + "$)", socket.gethostname())
if match:
return True


if check_env():
PRODUCTION = True
else:
PRODUCTION = False


DEBUG = not PRODUCTION

也许这样能帮到你。

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

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

下面是一个小例子(文件example/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的设置的博客。看看吧!

作为维护不同文件的替代方法: 如果您正在使用git或其他VCS将代码从本地推送到服务器,您可以做的是将设置文件添加到.gitignore.

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

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

为了在不同的环境中使用不同的settings配置,创建不同的设置文件。在你的部署脚本中,使用--settings=<my-settings.py>参数启动服务器,通过它你可以在不同的环境中使用不同的设置

使用这种方法的好处:

  1. 您的设置将基于每个环境模块化

  2. 你可以在environmnet_configuration.py中导入包含基本配置的master_settings.py,并覆盖你想要在该环境中更改的值。

  3. 如果你有一个庞大的团队,每个开发人员可能都有他们自己的local_settings.py,他们可以将其添加到代码库中,而无需修改服务器配置。如果你使用git,你可以将这些本地设置添加到.gitnore;如果你使用Mercurial for Version Control(或任何其他),你可以将这些本地设置添加到.hginore。这样,本地设置甚至不会成为实际代码库的一部分,以保持整洁。

还有Django Classy Settings。我个人是它的忠实粉丝。它是由Django IRC上最活跃的人之一构建的。你可以使用环境变量来设置。

< a href = " http://django-classy-settings.readthedocs。Io /en/latest/" rel="nofollow noreferrer">http://django-classy-settings.readthedocs.io/en/latest/

TL;DR:诀窍是在你在任何settings/<purpose>.py中导入settings/base.py之前修改os.environment,这将极大地简化事情。


一想到这些缠绕在一起的文件,我就头疼。 组合、导入(有时是有条件的)、重写、修补已经设置的内容,以防以后DEBUG设置发生变化。 真是个噩梦!< / p > 这些年来,我经历了各种不同的解决方案。他们都有些工作,但是如此痛苦的管理。 WTF !我们真的需要那么多麻烦吗?我们从一个settings.py文件开始。 现在我们需要一个文档,以正确的顺序将所有这些组合在一起!< / p >

我希望我终于用下面的解决方案达到了我的最佳境界。

让我们回顾一下目标(有些是共同的,有些是我的)

  1. 保守秘密——不要把它们储存在回购中!

  2. 通过环境设置来设置/读取密钥和秘密,12 factor style

  3. 设置合理的备用默认值。理想情况下,对于本地开发,除了默认值,您不需要任何其他东西。

  4. …但是尽量保持默认生产安全。最好错过局部的设置覆盖,

  5. 有能力以一种可以对其他设置产生影响的方式打开/关闭DEBUG。是否使用javascript压缩)。

  6. 在目的设置之间切换,如本地/测试/登台/生产,应该只基于DJANGO_SETTINGS_MODULE,仅此而已。

  7. 但是允许通过诸如DATABASE_URL这样的环境设置进一步参数化。

  8. 还允许它们使用不同的目的设置,并在本地并排运行它们,例如。在本地开发人员机器上进行生产设置,以访问生产数据库或测试压缩样式表。

  9. 如果没有显式地设置环境变量(至少需要一个空值),则失败,特别是在生产中,例如。EMAIL_HOST_PASSWORD

  10. django-admin startproject .py中回复默认的DJANGO_SETTINGS_MODULE

  11. 如果条件是目的环境类型,则将条件保持在最小值。对于生产集日志文件和它的旋转),覆盖相关的目的设置文件中的设置。

不的

  1. 不要让django读取DJANGO_SETTINGS_MODULE设置形成一个文件 啊!想想这有多复杂。如果你需要一个文件(如docker

  2. . Env)在启动django进程之前读入环境 不要在你的项目/应用代码中覆盖DJANGO_SETTINGS_MODULE,例如:基于主机名或进程名 如果你懒得设置环境变量(比如setup.py test),可以在运行项目代码之前在工具中设置
  3. 避免django读取设置的魔法和补丁,预处理设置,但之后不要干涉。

  4. 没有基于无意义的复杂逻辑。配置应该是固定和实体化的,而不是动态计算的。 在这里提供一个回退默认值就足够了 你真的想调试吗,为什么你在本地有正确的设置,但在生产中,在远程服务器上, 在一百台机器中的一台上,计算结果会有所不同?哦!单元测试呢?设置?严重吗?李< / p > < / >

解决方案

我的策略包括与ini样式文件一起使用的优秀django-environ, 为本地开发提供os.environment默认值,一些最小和简短的settings/<purpose>.py文件具有 import settings/base.py os.environment是从一个INI文件中设置的。这有效地给了我们一种设置注入

这里的技巧是在导入settings/base.py之前修改os.environment

要查看完整的示例,执行repo: https://github.com/wooyek/django-settings-strategy

.
│   manage.py
├───data
└───website
├───settings
│   │   __init__.py   <-- imports local for compatibility
│   │   base.py       <-- almost all the settings, reads from proces environment
│   │   local.py      <-- a few modifications for local development
│   │   production.py <-- ideally is empty and everything is in base
│   │   testing.py    <-- mimics production with a reasonable exeptions
│   │   .env          <-- for local use, not kept in repo
│   __init__.py
│   urls.py
│   wsgi.py

设置/ .env

本地开发的默认值。一个秘密文件,主要用于设置所需的环境变量。 如果在本地开发中不需要它们,则将它们设置为空值。 我们在这里提供默认值,而不是在settings/base.py中提供,如果从环境中缺失,则在任何其他机器上失败

设置/ local.py

这里发生的事情是从settings/.env加载环境,然后导入公共设置 从settings/base.py。在此之后,我们可以覆盖一些以简化局部开发
import logging
import environ


logging.debug("Settings loading: %s" % __file__)


# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')


from .base import *


ALLOWED_HOSTS += [
'127.0.0.1',
'localhost',
'.example.com',
'vagrant',
]


# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'


LOGGING['handlers']['mail_admins']['email_backend'] = 'django.core.mail.backends.dummy.EmailBackend'


# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager


CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True

设置/ production.py

对于生产,我们不应该期望有一个环境文件,但是如果我们正在测试一些东西,有一个环境文件会更容易。 但无论如何,唯恐函数内联提供了很少的默认值,因此settings/base.py可以相应地做出响应。< / p >
environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *
这里的主要兴趣点是DEBUGASSETS_DEBUG重写, 只有当它们在环境和文件中不存在时,它们才会被应用到python os.environ。< / p >

这些将是我们的产品默认值,不需要将它们放在环境或文件中,但如果需要,可以覆盖它们。整洁!

设置/ base.py

这些是你最普通的django设置,有一些条件和大量的从环境中读取它们。 几乎所有东西都在这里,保持所有目标环境的一致性和尽可能相似

主要区别如下(我希望这些是不言自明的):

import environ


# https://github.com/joke2k/django-environ
env = environ.Env()


# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))


# Where BASE_DIR is a django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your django project code is in `src` folder
# This may help to separate python modules and *django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/


# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)


INTERNAL_IPS = [
'127.0.0.1',
]


ALLOWED_HOSTS = []


if 'ALLOWED_HOSTS' in os.environ:
hosts = os.environ['ALLOWED_HOSTS'].split(" ")
BASE_URL = "https://" + hosts[0]
for host in hosts:
host = host.strip()
if host:
ALLOWED_HOSTS.append(host)


SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases


if "DATABASE_URL" in os.environ:  # pragma: no cover
# Enable database config through environment
DATABASES = {
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
'default': env.db(),
}


# Make sure we use have all settings we need
# DATABASES['default']['ENGINE'] = 'django.contrib.gis.db.backends.postgis'
DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
DATABASES['default']['OPTIONS'] = {
'options': '-c search_path=gis,public,pg_catalog',
'sslmode': 'require',
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
'TEST': {
'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
}
}
}

STATIC_ROOT = os.path.join(ROOT_DIR, 'static')


# django-assets
# http://django-assets.readthedocs.org/en/latest/settings.html


ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG)  # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
ASSETS_URL = STATIC_URL
ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
ASSETS_URL = STATIC_URL + "assets/compressed/"
ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)

最后一位显示了这里的力量。ASSETS_DEBUG有一个合理的默认值, 它可以在settings/production.py中被覆盖,甚至可以被环境设置覆盖!耶!< / p >

实际上,我们有一个混合的重要性等级:

  1. Settings /.py -根据目的设置默认值,不存储秘密
  2. Settings /base.py -主要由环境控制
  3. 进程环境设置- 12因素宝贝!
  4. 设置/。本地默认环境,便于启动

1 -在你的应用程序中创建一个新文件夹,并设置它的名称。

2 -现在在其中创建一个新的__init__.py文件,并在其中写入

from .base import *


try:
from .local import *
except:
pass


try:
from .production import *
except:
pass

3 -在设置文件夹中创建三个新文件local.pyproduction.pybase.py

4 -在base.py中,复制之前settings.py文件夹的所有内容,并将其重命名为不同的内容,例如old_settings.py

5 -在base.py中更改BASE_DIR路径以指向新的设置路径

- > < p >旧路 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) < / p >

新路径-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) < / p >

通过这种方式,项目总监可以结构化,并且可以在生产和本地开发之间进行管理。

我将我的设置拆分如下

settings/
|
|- base.py
|- dev.py
|- prod.py

我们有三种环境

  • dev
  • 暂存
  • 生产

现在,显然登台和生产应该有尽可能相似的环境。所以我们为两者保留prod.py

但是在这种情况下,我必须确定正在运行的服务器是生产服务器。@T。斯通的回答帮助我写了如下支票。

from socket import gethostname, gethostbyname
PROD_HOSTS = ["webserver1", "webserver2"]


DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]




if any(host in PROD_HOSTS for host in ALLOWED_HOSTS):
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
创建多个版本的settings.py是12因素App方法论的反模式。 使用python-decoupledjango-environ代替

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

if DEBUG:
from .local_settings import *

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