【问题标题】:How do you configure Django for simple development and deployment?您如何配置 Django 以进行简单的开发和部署?
【发布时间】:2010-09-10 10:28:49
【问题描述】:

我在做Django时倾向于使用SQLite 开发,但在实时服务器上更强大的是 经常需要(例如MySQL/PostgreSQL)。 总是对 Django 进行其他更改 设置以及:不同的记录位置/强度, 媒体路径等

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

【问题讨论】:

标签: python django


【解决方案1】:

更新:django-configurations 已发布,对于大多数人来说,这可能是比手动操作更好的选择。

如果您更喜欢手动操作,我之前的回答仍然适用:

我有多个设置文件。

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

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

这样,您真正需要担心的唯一一件事就是使settings_local.py 文件与主机特定的配置保持同步,其他一切都会自动处理。

查看示例 here

【讨论】:

  • 如果登台(开发)和生产在同一台机器上怎么办? platform.node() 则返回相同的结果。
  • 示例链接已关闭。
  • 根据主机列表确定设置的好主意!我的一个挑剔是命名法(settings_local.py 总是首先导入,因此任何未被覆盖的设置实际上仍将在生产中处于活动状态,使得后缀 _local 相当混乱)以及您没有使用的事实模块(settings/base.py、settings/local.py、settings/production.py)。将其保存在单独的存储库中也是明智之举……更好的是,一种从规范来源提供此信息的安全服务(对大多数人来说可能是多余的)……因此新主机不需要新版本。
  • 更好的是,如果您使用机器管理软件,而不是检查 .py 文件中的主机列表,从而使每个主机都可以访问有关其他主机的配置信息,您可以模板化 manage.py 以在部署配置中使用适当的设置文件。
【解决方案2】:

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

import socket
if socket.gethostname().startswith('gabriel'):
    LIVEHOST = False
else: 
    LIVEHOST = True

然后在其他部分我有类似的东西:

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/'

等等。可读性稍差,但它工作正常,并且无需处理多个设置文件。

【讨论】:

  • 我喜欢这个想法,但它不允许我区分在同一主机上运行的不同 Django 实例。例如,如果您在同一主机上为不同的子域运行不同的实例,就会发生这种情况。
【解决方案3】:

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

try:
    from settings_local import *
except ImportError:
    pass

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

【讨论】:

  • 这有点危险,因为如果settings_local 中的拼写错误导致ImportError,这个except 会默默吞下它。
  • 您可以查看No module named...cannot import name... 的消息,但它很脆弱。或者,将您的导入放在 try 块中的 settings_local.py 中并引发更具体的异常:MisconfiguredSettings 或类似的东西。
  • 可以使用最新版本的 Python except ModuleNotFoundError
【解决方案4】:

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

【讨论】:

  • 我也用这个。它优于逆向(在 settings.py 末尾的 dmshe 的“from settings_local import *”),因为它允许本地设置在需要时访问和修改全局设置。
  • 如果settings_local.py 这样做from settings import *,它可以覆盖settings.py 中的值。 (settings_local.py 文件必须在settings.py 的末尾导入)。
  • 无论如何都可以做到。看看上面的stackoverflow.com/a/7047633/3124256。 @Seth 这是循环导入的秘诀。
【解决方案5】:

我发现的最简单的方法是:

1) 使用默认的 settings.py 进行本地开发和 2) 创建一个 production-settings.py,开头为:

import os
from settings import *

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

DEBUG = False
TEMPLATE_DEBUG = DEBUG


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

【讨论】:

  • django 是如何知道加载生产设置的?
【解决方案6】:

有点相关,关于Django本身部署多个数据库的问题,大家不妨看看Djangostack。您可以下载一个完全免费的安装程序,允许您安装 Apache、Python、Django 等。作为安装过程的一部分,我们允许您选择要使用的数据库(MySQL、SQLite、PostgreSQL)。我们在内部自动化部署时广泛使用安装程序(它们可以在无人值守模式下运行)。

【讨论】:

【解决方案7】:

我的 settings.py 文件位于外部目录中。这样,它就不会被检查到源代码控制中,也不会被部署覆盖。我把它和任何默认设置一起放在我的 Django 项目下的 settings.py 文件中:

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,这是非常危险的。

【讨论】:

    【解决方案8】:

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

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

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

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

    【讨论】:

    • Ansible 是 python 并且提供比 Fabric 更强大的配置工具。它们也很搭。
    【解决方案9】:

    嗯,我用这个配置:

    settings.py 结尾:

    #settings.py
    try:
        from locale_settings import *
    except ImportError:
        pass
    

    在 locale_settings.py 中:

    #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
    

    【讨论】:

      【解决方案10】:

      这么多复杂的答案!

      每个 settings.py 文件都附带:

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

      我使用该目录来设置 DEBUG 变量,如下所示(用你的开发代码所在的目录替换):

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

      然后,每次移动 settings.py 文件时,DEBUG 都会为 False,这是你的生产环境。

      每当您需要与开发环境中的设置不同的设置时,只需使用:

      if(DEBUG):
          #Debug setting
      else:
          #Release setting
      

      【讨论】:

        【解决方案11】:

        我认为这取决于网站的规模是否需要停止使用 SQLite,我已经在几个较小的实时网站上成功使用了 SQLite,并且运行良好。

        【讨论】:

          【解决方案12】:

          我使用环境:

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

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

          【讨论】:

          • 请问您如何获得 settings_production 和 settings_dev 值?您的项目架构是什么?
          【解决方案13】:

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

          使用django-configuration

          快速入门

          pip install django-configurations
          

          然后在项目的 settings.py 或您用于存储设置常量的任何其他模块中子类化包含的configurations.Configuration 类,例如:

          # 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 管理命令时按照 Django 的默认 --settings 命令行选项提供--configuration 选项,例如:

          python manage.py runserver --settings=mysite.settings --configuration=Dev

          要让 Django 使用您的配置,您现在必须修改您的 ma​​nage.pywsgi.py 脚本以使用 django-configurations 的相应启动器功能版本,例如使用 django-configurations 的典型 ma​​nage.py 如下所示:

          #!/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 文件,例如:

          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

          就是这样!您现在可以将您的项目与 ma​​nage.py 和您最喜欢的支持 WSGI 的服务器一起使用。

          【讨论】:

            【解决方案14】:

            为什么要把事情搞得这么复杂?我从 PHP/Laravel 背景进入 Django。我用.env,你可以轻松配置。

            安装这个包

            django-environ
            

            现在,在 settings.py 所在的文件夹中,创建一个文件 .env(确保将此文件放在 gitignore 中)

            .env 文件中,放置环境变量,如调试设置状态、密钥、邮件凭据等 示例.env的快照

            SECRET_KEY="django-insecure-zy%)s5$=aql=#ox54lzfjyyx!&uv1-q0kp^54p(^251&_df75i"
            
            DB_NAME=bugfree
            DB_USER=postgres
            DB_PASSWORD=koushik
            DB_PORT=5433
            DB_HOST=localhost
            
            APP_DEBUG=True # everything is string here
            

            在设置中,确保使用 this 实例化它

            import environ
            env = environ.Env()
            environ.Env.read_env()
            

            现在您可以从.env 文件中导入值并将它们放在您想要的任何位置。 settings.py中的一些例子

            SECRET_KEY = env('SECRET_KEY')
            DEBUG = bool(env('APP_DEBUG', False))
            

            你也可以这样设置默认值

            env('DB_NAME', 'default value here')
            

            提示 您可以在您拥有.env 文件的同一文件夹中创建另一个.env.example,并且您可以拥有.env 的模板,并且您可以提交.example 文件。它可以帮助未来的开发人员轻松了解那里有哪些环境变量。 .env.example 会是这样的

            SECRET_KEY=VALUE_HERE
            
            DB_NAME=VALUE_HERE
            DB_USER=VALUE_HERE
            DB_PASSWORD=VALUE_HERE
            DB_PORT=VALUE_HERE
            DB_HOST=VALUE_HERE
            
            EMAIL_HOST=VALUE_HERE
            EMAIL_PORT=VALUE_HERE
            EMAIL_HOST_USER=VALUE_HERE
            EMAIL_HOST_PASSWORD=VALUE_HERE
            DEFAULT_FROM_EMAIL=VALUE_HERE
            

            【讨论】:

              【解决方案15】:

              事实上,您可能应该考虑为您的开发和生产环境使用相同(或几乎相同)的配置。否则时不时会出现“嘿,它在我的机器上运行”之类的情况。

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

              【讨论】:

                猜你喜欢
                • 2013-01-15
                • 1970-01-01
                • 2021-11-06
                • 2018-03-26
                • 2015-11-08
                • 1970-01-01
                • 1970-01-01
                • 2012-02-20
                相关资源
                最近更新 更多