代码之家  ›  专栏  ›  技术社区  ›  akv

如何管理Django的本地与生产设置?

  •  268
  • akv  · 技术社区  · 16 年前

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

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

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

    22 回复  |  直到 7 年前
        1
  •  123
  •   alexmuller    12 年前

    settings.py 以下内容:

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

    您可以覆盖 local_settings.py ;那么它应该远离版本控制。但既然你提到复制,我猜你一点用都不用;)

        2
  •  268
  •   gene_wood X-Istence    11 年前

    Two Scoops of Django: Best Practices for 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.py production.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
    

    这本书的作者也提出 a sample project layout template 在吉瑟布上。

        3
  •  63
  •   MiniQuark    13 年前

    而不是 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.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. 大多数配置都位于一个位置: 普通的 .
    3. 产品特定的东西进入 脯氨酸 ,特定于开发人员的内容 偏差PY . 这很简单。
    4. 您可以覆盖来自 普通的 在里面 脯氨酸 德芙 ,您可以覆盖 _初始版本 .
    5. 这是一条直截了当的巨蟒。没有重新导入的黑客。
        4
  •  20
  •   T. Stone    16 年前

    我使用了哈珀·谢尔比发布的稍微修改过的“if-debug”设置样式。显然,根据环境(win/linux/etc),代码可能需要稍作调整。

    我以前使用过“if-debug”,但我发现有时候我需要使用deubg设置为false进行测试。我真正想要区分的是环境是生产还是开发,这给了我选择调试级别的自由。

    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设置文件方法)。

        5
  •  14
  •   Kai    16 年前

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

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

        6
  •  7
  •   sobolevn akiraak    9 年前

    我通过以下方式管理配置: 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()
        )
    

    就这样。

    更新

    我写了一篇 blog post 关于管理 django 的设置 django-split-sttings . 看一看!

        7
  •  6
  •   rewritten    14 年前

    大多数这些解决方案的问题是,要么应用本地设置 之前 普通的,或 之后 他们。

    所以不可能超越

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

    同时。

    一个解决方案可以使用带有configParser类的“ini”样式的配置文件来实现。它支持多个文件、延迟字符串插值、默认值和许多其他优点。 一旦加载了多个文件,就可以加载更多的文件,如果有的话,这些文件的值将覆盖以前的文件。

    根据机器地址、环境变量甚至之前加载的配置文件中的值,可以加载一个或多个配置文件。然后您只需使用解析的值来填充设置。

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

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

    作为一个可以用这个实现的示例,您可以为每个env定义一个“子域”值,然后在默认设置中使用该值(如 hostname: %(subdomain).whatever.net )为了定义所有必要的主机名和cookie,Django需要工作。

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

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

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

        8
  •  5
  •   Janusz Skonieczny    9 年前

    窍门是修改 os.environment 在导入之前 settings/base.py 在任何 settings/<purpose>.py ,这将大大简化事情。


    想到这些相互缠绕的文件,我就头疼。 组合、导入(有时有条件)、重写、修补已设置的内容以防 DEBUG 设置稍后更改。 真是个噩梦!

    这些年来,我经历了所有不同的解决方案。他们都 有点 工作,但管理起来很痛苦。 世界跆拳道联盟!我们真的需要这么多麻烦吗?我们从一个开始 settings.py 文件。 现在我们需要一个文档来正确地将所有这些按正确的顺序组合在一起!

    我希望我终于找到了下面的解决方案。

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

    1. 保守秘密一个秘密,不要把它们储存在回购协议中。

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

    3. 具有合理的回退默认值。对于本地开发来说,除了默认值之外,您不需要其他任何东西。

    4. _但尽量保持默认生产安全。最好在本地忽略设置覆盖, 比必须记住调整默认设置安全生产。

    5. 能够转换 调试 以一种对其他设置有影响的方式打开/关闭(例如,是否使用Javascript压缩)。

    6. 在目的设置之间切换,如本地/测试/分段/生产,应仅基于 DJANGO_SETTINGS_MODULE 没有别的了。

    7. _但允许通过环境设置进行进一步的参数化,如 DATABASE_URL .

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

    9. 如果未显式设置环境变量(至少需要空值),则失败,尤其是在生产环境中,例如。 EMAIL_HOST_PASSWORD .

    10. 响应默认值 Django_设置_模块 在期间在manage.py中设置 django-admin startproject

    11. 如果条件为 这个 目标环境类型(例如,对于生产集日志文件及其旋转),覆盖关联目标设置文件中的设置。

    不要

    1. 不要让django读取django_设置_模块设置形成文件。
      呸!想想这是多么的元。如果你需要一个文件(比如Docker env)在启动Django进程之前将其读到环境中。

    2. 不要覆盖项目/应用程序代码中的django_设置_模块,例如基于主机名或进程名。
      如果您懒得设置环境变量(例如 setup.py test )在运行项目代码之前,在工具中完成它。

    3. 避免魔术和补丁如何德詹戈读取它的设置,预处理设置,但不要干涉以后。

    4. 没有复杂的逻辑基础的废话。配置应该是固定的和物化的,而不是动态计算的。 提供一个回退默认值只是这里的逻辑而已。
      您真的想调试,为什么在本地设置正确,但在远程服务器上生产, 在一百台机器中,有什么计算方法不同吗?哦!单元测试?设置?真的吗?

    解决方案

    我的策略包括优秀 django-environ 用于 ini 样式文件, 提供 OS.环境 本地开发的默认值,一些最小值和短值 设置/<目的>.py 具有 import settings/base.py 这个 OS.环境 从一个 INI 文件。这实际上给了我们一种设置注入。

    这里的诀窍是修改 OS.环境 在导入之前 设置/base.py .

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

    .
    │   manage.py
    ├───data
    └───website
        ├───settings
        │   │   __init__.py   <-- imports local for compatybility
        │   │   base.py       <-- almost all the settings, reads from proces environment 
        │   │   local.py      <-- a few modifications for local development
        │   │   production.py <-- ideally is empy 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
    

    设置/

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

    设置/local.py

    这里发生的事情是从 settings/.env ,然后导入公用设置 从 设置/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
    

    设置/生产.py

    对于生产,我们不应该期望有一个环境文件,但是如果我们在测试一些东西,就更容易有一个。 但不管怎么说,test提供了很少的内联默认值,所以 设置/base.py 可以做出相应的反应。

    environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
    from .base import *
    

    这里的主要兴趣点是 调试 ASSETS_DEBUG 重写, 它们将应用于python os.environ 仅当它们在环境和文件中丢失时。

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

    设置/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',)
    

    最后一位显示了这里的功率。 资产调试 有合理的违约, 可以在中重写 settings/production.py 甚至可以被环境设置覆盖!哎呀!

    实际上,我们有一个复杂的重要性层次:

    1. settings/.py-根据目的设置默认值,不存储机密
    2. settings/base.py-主要由环境控制
    3. 过程环境设置-12因子宝贝!
    4. settings/.env-轻松启动的本地默认值
        9
  •  4
  •   Harper Shelby damiankolasa    16 年前

    记住,settings.py是一个实时代码文件。假设在生产环境中没有调试集(这是一种最佳实践),可以执行以下操作:

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

    非常基本,但是理论上,您可以根据调试的值或者您想要使用的任何其他变量或代码检查达到任何复杂程度。

        10
  •  4
  •   Robert Kuzma    12 年前

    我也在与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
    

    也许像这样的东西能帮到你。

        11
  •  3
  •   Miguel Ventura    16 年前

    我对这个问题的解决方案也有点混合了一些已经在这里说明的解决方案:

    • 我有一个叫 local_settings.py 有内容的 USING_LOCAL = True 在开发和 USING_LOCAL = False 在PRD中
    • settings.py 我对该文件执行导入以获取 USING_LOCAL 设置

    然后,我将所有依赖于环境的设置都基于该设置:

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

    我更喜欢使用两个单独的settings.py文件,因为我可以将设置保持在单个文件中,而不是将它们分散在多个文件中。像这样,当我更新一个设置时,我不会忘记为两个环境都这样做。

    当然,每种方法都有其缺点,这一点也不例外。这里的问题是我不能覆盖 本地设置.py 每当我把我的更改推到生产中时,都要归档,这意味着我不能盲目地复制所有的文件,但这是我可以忍受的。

        12
  •  3
  •   dzida    15 年前

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

    1. 创建设置_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 )

        13
  •  3
  •   stratosgear    15 年前

    我使用了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)
    

    基本上,在每台计算机(开发或生产)上,我都有相应的主机名_settings.py文件,可以动态加载。

        14
  •  3
  •   SudoKid    9 年前

    还有Django Classy设置。我个人很喜欢它。它是由Django IRC上最活跃的人建造的。您将使用环境变量来设置内容。

    http://django-classy-settings.readthedocs.io/en/latest/

        15
  •  2
  •   Moinuddin Quadri    9 年前

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

    使用这种方法的好处 :

    1. 您的设置将根据每个环境进行模块化。

    2. 您可以导入 master_settings.py 包含中的基本配置 environmnet_configuration.py 并重写要在该环境中更改的值。

    3. 如果你有一个庞大的团队,每个开发人员可能都有自己的团队。 local_settings.py 它们可以添加到代码存储库中,而不会有修改服务器配置的风险。您可以将这些本地设置添加到 .gitnore 如果你使用 吉特 .hginore 如果你 水银的 对于 版本控制 (或任何其他)。这样,本地设置甚至不会成为保持代码库干净的一部分。

        16
  •  1
  •   Joshua Partogi    16 年前

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

    我发现将设置文件分为两个单独的文件要容易一些,而不是在设置文件中进行大量的IFS。

        17
  •  1
  •   sprksh    10 年前

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

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

    此外,它还将从Github中删除settings.py文件,这是一个很大的错误,我已经看到许多新手在做这个。

        18
  •  1
  •   Kishor Pawar    9 年前

    我的设置拆分如下

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

    我们有3个环境

    • DEV
    • 分期
    • 生产

    很明显,分段生产应该有尽可能多的相似环境。所以我们保持 prod.py 两者兼而有之。

    但有一个案例,我必须确定运行的服务器是生产服务器。@斯通的回答帮助我写了如下支票。

    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  
    
        19
  •  1
  •   ilse2005    7 年前

    1-在应用程序中创建一个新文件夹并为其命名设置。

    2-现在创建新的 初始化 .py文件在其中并在其中写入

        from .base import *
    
        try:
    
            from .local import *
    
        except:
    
            pass
    
         try:
    
             from .production import *
    
         except:
    
             pass
    

    3-在设置文件夹中创建三个新文件:local.py和production.py以及base.py。

    4-在base.py中,复制先前settings.p文件夹中的所有内容,并用不同的名称重命名,比如说old_settings.py。

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

    旧路径->base_dir=os.path.dirname(os.path.dirname(os.path.abspath)( 文件 ))

    新路径->base_dir=os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath)( 文件 ))

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

        20
  •  0
  •   Mustapha-Belkacim    7 年前

    制作多个版本的settings.py是 12 Factor App methodology . 使用 python-decouple django-environ 相反。

        21
  •  0
  •   smrf markus-hinsche    7 年前

    我认为最好的解决方案是由@t.stone提出的,但我不知道为什么不在django中使用debug标志。我为我的网站编写以下代码:

    if DEBUG:
        from .local_settings import *
    

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

        22
  •  -3
  •   Jason Boyd    12 年前

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

    我的标准是:

    • 一切 应该在源代码管理中。我不喜欢到处胡闹。
    • 理想情况下,将设置保存在一个文件中。如果我看得不对,我就会忘记这些事情。)
    • 没有要部署的手动编辑。应该能够使用单个结构命令测试/推送/部署。
    • 避免将开发设置泄漏到生产中。
    • 尽可能靠近“标准”(*咳嗽*)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_概要文件中还是在任何地方:

    $ export DJANGO_DEVELOPMENT_SERVER=yep
    

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

    使用这种方法,开发人员设置都在一个(标准)位置,并且只需在需要时覆盖生产设置。任何与开发设置有关的混乱都应该是完全安全的,以承诺在不影响生产的情况下进行源代码控制。