178

我一直在开发一个基本的应用程序。现在在部署阶段,很明显我需要本地设置和生产设置。

很高兴知道以下内容:

  • 如何最好地处理开发和生产设置。
  • 如何将 django-debug-toolbar 等应用程序仅保留在开发环境中。
  • 有关开发和部署设置的任何其他提示和最佳实践。
4

19 回答 19

142

DJANGO_SETTINGS_MODULE环境变量控制 Django将加载哪些设置文件。

因此,您可以为各自的环境创建单独的配置文件(请注意,它们当然可以import *来自单独的“共享设置”文件),并用于DJANGO_SETTINGS_MODULE控制要使用的配置文件。

就是这样:

如 Django 文档中所述:

DJANGO_SETTINGS_MODULE 的值应该是 Python 路径语法,例如 mysite.settings。请注意,设置模块应位于 Python 导入搜索路径中。

因此,让我们假设您创建myapp/production_settings.pymyapp/test_settings.py在您的源存储库中。

在这种情况下,您将分别设置DJANGO_SETTINGS_MODULE=myapp.production_settings为使用前者和DJANGO_SETTINGS_MODULE=myapp.test_settings使用后者。


从这里开始,问题归结为设置DJANGO_SETTINGS_MODULE环境变量。

DJANGO_SETTINGS_MODULE使用脚本或 shell 进行设置

然后,您可以使用引导脚本或进程管理器来加载正确的设置(通过设置环境),或者在启动 Django 之前从 shell 运行它:export DJANGO_SETTINGS_MODULE=myapp.production_settings

请注意,您可以随时从 shell 运行此导出 - 它不需要存在于您的.bashrc或任何东西中。

DJANGO_SETTINGS_MODULE使用进程管理器进行设置

如果您不喜欢编写设置环境的引导脚本(并且有充分的理由有这种感觉!),我建议您使用流程管理器:


最后,请注意,您可以利用该PYTHONPATH变量将设置存储在完全不同的位置(例如,在生产服务器上,将它们存储在 中/etc/)。这允许将配置与应用程序文件分开。您可能想要也可能不想要,这取决于您的应用程序的结构。

于 2012-05-19T10:36:40.923 回答
101

默认情况下使用生产设置,但在与您的文件settings_dev.py相同的文件夹中创建一个名为的settings.py文件。在那里添加覆盖,例如DEBUG=True.

在将用于开发的计算机上,将其添加到您的~/.bashrc文件中:

export DJANGO_DEVELOPMENT=true

settings.py文件的底部,添加以下内容。

# Override production variables if DJANGO_DEVELOPMENT env variable is set
if os.environ.get('DJANGO_DEVELOPMENT'):
    from settings_dev import *  # or specific overrides

(请注意,*在 Python 中通常应避免导入)

默认情况下,生产服务器不会覆盖任何内容。完毕!

与其他答案相比,这个答案更简单,因为它不需要更新PYTHONPATH或设置DJANGO_SETTINGS_MODULE,它一次只允许您处理一个 django 项目。

于 2016-01-20T04:39:44.677 回答
38

我通常每个环境有一个设置文件和一个共享设置文件:

/myproject/
  settings.production.py
  settings.development.py
  shared_settings.py

我的每个环境文件都有:

try:
    from shared_settings import *
except ImportError:
    pass

这允许我在必要时覆盖共享设置(通过在该节下方添加修改)。

然后我通过将其链接到 settings.py 来选择要使用的设置文件:

ln -s settings.development.py settings.py
于 2012-05-19T11:28:31.033 回答
37

这就是我通过 6 个简单步骤完成的方法:

  1. 在您的项目目录中创建一个文件夹并将其命名为settings.

    项目结构:

    myproject/
           myapp1/
           myapp2/              
           myproject/
                  settings/
    
  2. 在目录中创建四个 python 文件,settings__init__.py、和base.pydev.pyprod.py

    设置文件:

    settings/
         __init__.py
         base.py
         prod.py
         dev.py 
    
  3. 打开__init__.py并填写以下内容:

    初始化.py:

    from .base import *
    # you need to set "myproject = 'prod'" as an environment variable
    # in your OS (on which your website is hosted)
    if os.environ['myproject'] == 'prod':
       from .prod import *
    else:
       from .dev import *
    
  4. 打开base.py并用所有常用设置(将在生产和开发中使用)填充它。例如:

    基础.py:

    import os
    ...
    INSTALLED_APPS = [...]
    MIDDLEWARE = [...]
    TEMPLATES = [{...}]
    ...
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    MEDIA_ROOT = os.path.join(BASE_DIR, '/path/')
    MEDIA_URL = '/path/'
    
  5. 打开dev.py并包含特定于开发的内容,例如:

    开发者.py:

    DEBUG = True
    ALLOWED_HOSTS = ['localhost']
    ...
    
  6. 打开prod.py并包含特定于生产的内容,例如:

    产品.py:

    DEBUG = False
    ALLOWED_HOSTS = ['www.example.com']
    LOGGING = [...]
    ...
    
  7. (根据 ANDRESMA 的评论)更新BASE_DIR您的文件以通过在末尾base.py添加另一个来反映您更新的路径。.parent例如:

    基础.py:

    BASE_DIR = Path(__file__).resolve().parent.parent.parent
    
于 2019-01-21T15:21:02.613 回答
12

我使用了很棒的django-configurations,所有设置都存储在我的settings.py

from configurations import Configuration

class Base(Configuration):
    # all the base settings here...
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ...

class Develop(Base):
    # development settings here...
    DEBUG = True 
    ...

class Production(Base):
    # production settings here...
    DEBUG = False

要配置 Django 项目,我只是按照文档

于 2017-03-14T20:56:44.330 回答
11

创建多个settings*.py文件,推断每个环境需要更改的变量。然后在你的主settings.py文件的末尾:

try:
  from settings_dev import *
except ImportError:
  pass

settings_*您为每个阶段保留单独的文件。

settings_dev.py文件的顶部,添加以下内容:

import sys
globals().update(vars(sys.modules['settings']))

导入需要修改的变量。

这个wiki 条目有更多关于如何拆分设置的想法。

于 2012-05-19T10:24:31.303 回答
11

这是我们使用的方法:

  • settings将设置拆分为多个文件以提高可读性的模块;
  • 一个.env.json文件,用于存储我们希望从 git 存储库中排除或特定于环境的凭据和参数;
  • 读取文件env.py.env.json文件

考虑以下结构:

...
.env.json           # the file containing all specific credentials and parameters
.gitignore          # the .gitignore file to exclude `.env.json`
project_name/       # project dir (the one which django-admin.py creates)
  accounts/         # project's apps
    __init__.py
    ...
  ...
  env.py            # the file to load credentials
  settings/
    __init__.py     # main settings file
    database.py     # database conf
    storage.py      # storage conf
    ...
venv                # virtualenv
...

喜欢.env.json

{
    "debug": false,
    "allowed_hosts": ["mydomain.com"],
    "django_secret_key": "my_very_long_secret_key",
    "db_password": "my_db_password",
    "db_name": "my_db_name",
    "db_user": "my_db_user",
    "db_host": "my_db_host",
}

并且project_name/env.py

<!-- language: lang-python -->
import json
import os


def get_credentials():
    env_file_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    with open(os.path.join(env_file_dir, '.env.json'), 'r') as f:
        creds = json.loads(f.read())
    return creds


credentials = get_credentials()

我们可以有以下设置:

<!-- language: lang-py -->
# project_name/settings/__init__.py
from project_name.env import credentials
from project_name.settings.database import *
from project_name.settings.storage import *
...

SECRET_KEY = credentials.get('django_secret_key')

DEBUG = credentials.get('debug')

ALLOWED_HOSTS = credentials.get('allowed_hosts', [])

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    ...
]

if DEBUG:
    INSTALLED_APPS += ['debug_toolbar']

...

# project_name/settings/database.py
from project_name.env import credentials

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': credentials.get('db_name', ''),
        'USER': credentials.get('db_user', ''),
        'HOST': credentials.get('db_host', ''),
        'PASSWORD': credentials.get('db_password', ''),
        'PORT': '5432',
    }
}

该解决方案的好处是:

  • 用于本地开发的用户特定凭据和配置,无需修改 git 存储库;
  • 特定于环境的配置,例如,您可以拥有三个不同的环境,其中包括三个不同的环境,.env.json例如开发、临时和生产;
  • 凭据不在存储库中

我希望这会有所帮助,如果您对此解决方案有任何警告,请告诉我。

于 2018-03-22T21:57:20.390 回答
4

我使用以下文件结构:

project/
   ...
   settings/
   settings/common.py
   settings/local.py
   settings/prod.py
   settings/__init__.py -> local.py

链接(unix中的ln或windows中的__init__.pymklink)local.py也是如此为生产环境运行命令。prod.pyproject.settingsDJANGO_SETTINGS_MODULEproject.settings.prod

在文件prod.pylocal.py

from .shared import *

DATABASE = {
    ...
}

并且该shared.py文件在没有特定配置的情况下保持为全局。

于 2017-11-16T18:44:48.097 回答
3

建立 cs01 的答案:

如果您遇到环境变量问题,请将其值设置为字符串(例如 I did DJANGO_DEVELOPMENT="true")。

我还更改了 cs01 的文件工作流程,如下所示:

#settings.py
import os
if os.environ.get('DJANGO_DEVELOPMENT') is not None:
    from settings_dev import * 
else:
    from settings_production import *
#settings_dev.py
development settings go here
#settings_production.py
production settings go here

这样,Django 在运行适当的设置文件之前不必通读整个设置文件。如果您的生产文件需要仅在生产服务器上的内容,则此解决方案会派上用场。

注意:在 Python 3 中,导入的文件需要.附加(例如from .settings_dev import *

于 2017-08-24T14:03:55.327 回答
3

用于settings.py生产。在同一目录settings_dev.py中为覆盖创建。

# settings_dev.py

from .settings import * 

DEBUG = False

在开发机器上运行您的 Django 应用程序:

DJANGO_SETTINGS_MODULE=<your_app_name>.settings_dev python3 manage.py runserver

在 prod 机器上运行,就好像你刚刚拥有settings.py,没有别的。

好处

  1. settings.py(用于生产)完全不知道任何其他环境甚至存在的事实。
  2. 要查看 prod 和 dev 之间的区别,您只需查看一个位置 - settings_dev.py. 无需收集分散在settings_prod.py,settings_dev.pysettings_shared.py.
  3. 如果有人在解决生产问题后将设置添加到您的产品配置中,您可以放心,它也会出现在您的开发配置中(除非明确覆盖)。因此,不同配置文件之间的差异将被最小化。
于 2019-10-25T10:16:34.797 回答
2

如果您想保留 1 个设置文件,并且您的开发操作系统与生产操作系统不同,则可以将其放在 settings.py 的底部:

from sys import platform
if platform == "linux" or platform == "linux2":
    # linux
    # some special setting here for when I'm on my prod server
elif platform == "darwin":
    # OS X
    # some special setting here for when I'm developing on my mac
elif platform == "win32":
    # Windows...
    # some special setting here for when I'm developing on my pc

阅读更多:如何在 Python 中检查操作系统?

于 2016-12-07T03:09:36.057 回答
1

这似乎已经得到解答,但是我结合版本控制使用的方法如下:

在与我也添加到 .gitignore 的本地开发环境中的设置相同的目录中设置一个 env.py 文件:

环境.py:

#!usr/bin/python

DJANGO_ENV = True
ALLOWED_HOSTS = ['127.0.0.1', 'dev.mywebsite.com']

.gitignore:

mywebsite/env.py

设置.py:

if os.path.exists(os.getcwd() + '/env.py'):
    #env.py is excluded using the .gitignore file - when moving to production we can automatically set debug mode to off:
    from env import *
else:
    DJANGO_ENV = False

DEBUG = DJANGO_ENV

我只是发现这很有效并且更加优雅 - 使用 env.py 可以很容易地查看我们的本地环境变量,我们可以在没有多个 settings.py 文件或类似文件的情况下处理所有这些。这种方法允许使用我们不想在生产服务器上设置的各种本地环境变量。通过版本控制利用 .gitignore,我们还保持一切无缝集成。

于 2017-09-16T17:53:14.357 回答
1

对于设置文件的问题,我选择复制

Project
   |---__init__.py   [ write code to copy setting file from subdir to current dir]
   |---settings.py  (do not commit this file to git)
   |---setting1_dir
   |         |--  settings.py
   |---setting2_dir
   |         |--  settings.py

当你运行 django 时,会运行 __init__py。这时候,settings.py in setting1_dir就要更换了settings.py in Project

如何选择不同的环境?

  • 直接修改__init__.py
  • 制作一个 bash 文件来修改__init__.py.
  • 在linux中修改env,然后__init__.py读取这个变量。

为什么要用这种方式?

因为我不喜欢同一个目录下那么多文件,太多的文件会迷惑其他小伙伴,对IDE也不是很好。(IDE找不到我们用的什么文件)

如果您不想看到所有这些细节,您可以将项目分为两部分。

  1. 制作像 Spring Initializr 这样的小工具,只是为了设置你的项目。(像复制文件一样做某事)
  2. 你的项目代码
于 2020-02-09T05:45:57.377 回答
0

我正在使用不同的 app.yaml 文件来更改谷歌云应用引擎中环境之间的配置。

您可以使用它在终端命令中创建代理连接:

./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:1433

https://cloud.google.com/sql/docs/sqlserver/connect-admin-proxy#macos-64-bit

文件:app.yaml

# [START django_app]
service: development
runtime: python37

env_variables:
  DJANGO_DB_HOST: '/cloudsql/myproject:myregion:myinstance'
  DJANGO_DEBUG: True

handlers:
# This configures Google App Engine to serve the files in the app's static
# directory.
- url: /static
  static_dir: static/

# This handler routes all requests not caught above to your main app. It is
# required when static routes are defined, but can be omitted (along with
# the entire handlers section) when there are no static files defined.
- url: /.*
  script: auto
# [END django_app]
于 2020-06-23T09:51:45.827 回答
0

我在生产的工作目录中创建了一个名为“production”的文件。

#settings.py
production = Path("production")
DEBUG = False

#if it's dev mode
if not production.is_file():
    INSTALLED_APPS +=[
       #apps_in_development_mode,
       #...
    ]
    DEBUG = True
    #other settings to override the default production settings
于 2021-08-05T00:01:36.090 回答
0

您希望能够根据您所在的 git 分支并依赖不同的设置文件来切换设置、秘密、环境变量和其他设置,但在企业情况下,您希望从存储库中隐藏所有敏感信息。向所有开发人员公开所有环境变量和所有环境(开发、登台、生产、质量保证等)的机密并不是最佳安全实践。以下应达到2。

  1. 根据部署环境隔离设置
  2. 从 git repo 隐藏敏感信息

我的 run.sh

#!/bin/bash
# default environment
export DJANGO_ENVIRONMENT="develop"
BRANCH=$(git rev-parse --abbrev-ref HEAD)

if [ $BRANCH == "main" ]; then
    export DJANGO_ENVIRONMENT="production"
elif [ $BRANCH == "release/"* ]; then
    export DJANGO_ENVIRONMENT="staging"
else
    # for all other branches (feature, support, hotfix etc.,)
    echo ''
fi

echo "
BRANCH: $BRANCH
ENVIRONMENT: $DJANGO_ENVIRONMENT
"
python3 myapp/manage.py makemigrations
python3 myapp/manage.py migrate --noinput
python3 myapp/manage.py runserver 0:8000

我的 vars.py(或 secrets.py 或任何名称)与 django 的 settings.py 位于同一文件夹中

vars = {
    'develop': {
        'environment': 'develop',
        'SECRET_KEY': 'mysecretkey',
        "DEBUG": "True"
        },
    'production': {
        'environment': 'production',
        'SECRET_KEY': 'mysecretkey',
        "DEBUG": "False"
        },
    'staging': {
        'environment': 'staging',
        'SECRET_KEY': 'mysecretkey',
        "DEBUG": "True"
        }
    }

然后在 settings.py 中执行以下操作

from . import vars # container environment specific vars
import os

DJANGO_ENVIRONMENT = os.getenv("DJANGO_ENVIRONMENT")  # declared in run.sh
envs = vars.vars[DJANGO_ENVIRONMENT] # SECURITY WARNING: keep the secret key 
used in production secret!
SECRET_KEY = envs["SECRET_KEY"]

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = envs["DEBUG"]

让开发人员在他们的本地机器上拥有自己的 vars.py,但是在部署期间,您的 cicd 管道可以插入带有实际值的实际 vars.py,或者某些脚本应该插入它。如果您使用的是 gitlab cicd 那么您可以将整个 vars.py 存储为环境变量

于 2021-08-31T20:12:49.913 回答
0

您可能会使用 wsgi.py 文件进行生产(该文件是在您创建 django 项目时自动创建的)。该文件指向一个设置文件。因此,制作一个单独的生产设置文件并在您的 wsgi.py 文件中引用它。

于 2021-09-13T02:40:14.830 回答
0

我们在这里所做的是为每个环境创建一个 .ENV 文件。该文件包含很多变量,例如ENV=development

settings.py 文件基本上就是一堆 os.environ.get(),比如ENV = os.environ.get('ENV')

因此,当您需要访问时,您可以这样做ENV = settings.ENV

您必须有一个用于生产、测试​​和开发的 .env 文件。

于 2022-03-02T00:25:06.837 回答
-2

这是我的解决方案,具有不同的开发、测试和生产环境

import socket

[...]

DEV_PC = 'PC059'
host_name = socket.gethostname()

if host_name == DEV_PC:
   #do something
   pass
elif [...]
于 2016-10-03T09:21:44.860 回答