Django本地设置

78 投票
8 回答
78835 浏览
提问于 2025-04-16 11:18

我正在尝试在 Django 1.2 中使用 local_setting,但它对我没有用。目前我只是把 local_settings.py 加入到我的项目中。

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'banco1',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

local_settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'banco2',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

问题是 local_settings.py 并没有覆盖 settings.py。这是怎么回事呢?

8 个回答

11

这个话题经常被提起,所以我来总结一下为什么你可能会考虑这种方法:

  • 一个简单的设置文件非常快且容易修改;尤其是在生产环境中。你不需要懂Python:任何人都可以直接打开文件,改一下数据库密码,这个文件里只列出了名字和值;相比于那些复杂的Python设置文件,里面充满了神秘又危险的大写字母名字,简单多了。

  • 应用的 settings 应该和应用的 code 完全分开。你可以把一个 config.ini 文件放在代码库的外面,这样就不用担心拉取代码库时会覆盖你的设置,或者你的个人设置会污染代码库,或者你在 settings.py 里写的聪明代码没法让其他人用到。

这对小项目可能不适用,但在大项目中,我发现本地设置的策略根本行不通;随着时间的推移,应用编程的内容会逐渐增多,变得难以处理;主要是因为设置之间会变得相互依赖。设置根据本地设置做出反应是有合理理由的,这就导致需要引入一个 local_settings 文件,慢慢地这个文件就会变得复杂。我发现事情开始变得混乱。

我现在的解决方案是使用一个 config 文件,我叫它 "local.ini"。它只包含那些在不同部署实例之间确实会变化的值。这里没有代码:只有值和布尔值:

[global]
domain = 127.0.0.1:8000
database_host = 127.0.0.1
database_name = test_database
debug = Yes
google_analytics_id = UA-DEV-1
payments = testing
use_cdn = No

有了这个,我可以把 settings.py 当作其他任何应用代码来处理:修改它,提交它,然后部署,而不必担心测试时会受到本地设置 Python 代码的影响。我的 settings.py 不会出现后续设置依赖于本地设置的竞争条件,我可以通过简单明了的线性代码来开启或关闭功能。再也不用匆忙修改本地设置文件,因为我忘记添加某个新值,也不再有 daves_local_settings.pybobs_local_settings.py 这样的文件混入代码库。

from ConfigParser import RawConfigParser
parser = RawConfigParser()

APPLICATION_ROOT = path.abspath(path.dirname(__file__))
parser.readfp(open(path.join(APPLICATION_ROOT, 'local.ini')))

# simple variables
DATABASE_HOST = parser.get('global', 'database_host')
DATABASE_NAME = parser.get('global', 'database_name')

# interdependencies
from version import get_cdn_version
CDN = 'd99phdomw5k72k.cloudfront.net'
if parser.getboolean('global', 'use_cdn'):
    STATIC_URL = '/{}/static/{}/'.format(CDN, get_cdn_version())
else:
    STATIC_URL = '/static/'


# switches
payments = parser.get('global', 'payments')
if payments == 'testing':
    PAYMENT_GATEWAY_ENDPOINT = 'https://api.sandbox.gateway.com'
else:
    PAYMENT_GATEWAY_ENDPOINT = 'https://api.live.gateway.com'

如果你遇到过一个 BOFH,就像我曾经遇到的那样,他对把 local.ini 放到 /etc 目录下,作为 /etc/ourapp.ini 感到特别兴奋,这样就能保持应用目录本身是一个纯粹的代码库导出。你当然可以用 local_settings.py 来做到这一点,但他最不想做的就是去碰 Python 代码。一个简单的配置文件他能处理。

87

我觉得这是最好的做法:

  • local_settingssettings 中导入
  • local_settings 会覆盖本地环境特有的设置,特别是 DATABASES(数据库)、SECRET_KEY(密钥)、ALLOWED_HOSTS(允许的主机)和 DEBUG(调试)这些变量
  • 在运行 Django 管理命令时,使用标志 --settings=local_settings

你可以这样实现 local_settings

from settings import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'banco2',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

还有一些额外的关键点:

  • settings.py 文件是版本控制的一部分,写得很适合贡献者使用
  • local_settings.py(或者更常见的 prod_settings.py)不在版本控制中,生产环境中使用时需要指定 --settings=prod_settings 或类似的命令。

尽量少动原始的设置文件,这样在升级 Django 版本时会更简单。当你把 Django 升级到下一个版本时,可以对比一下原始的 settings.py 和你的文件,看看有什么变化,然后根据变化做出相应的调整。默认值的变化可能很重要,越少改动原始的 settings.py 文件,越容易发现上游的变化。

149

你不能仅仅添加 local_settings.py 文件,还需要明确地导入它。

在你的 settings.py 文件的 最后,添加以下内容:

try:
    from local_settings import *
except ImportError:
    pass

这个 try/except 块的作用是,当你没有实际定义 local_settings 文件时,Python 会忽略这个情况,不会报错。

撰写回答