Python Django 本地设置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4909958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 18:04:47  来源:igfitidea点击:

Django Local Settings

pythondjangosettings

提问by Michel Andrade

I'm trying to use local_setting in Django 1.2, but it's not working for me. At the moment I'm just adding local_settings.pyto my project.

我正在尝试在Django 1.2 中使用 local_setting ,但它对我不起作用。目前我只是将local_settings.py添加到我的项目中。

settings.py

设置.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

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.
    }
}

The problem is that local_settings.pydoesn't override settings.py. What is wrong?

问题是local_settings.py不会覆盖settings.py。怎么了?

采纳答案by Daniel Roseman

You can't just add local_settings.py, you have to explicity import it.

您不能只添加 local_settings.py,您必须明确导入它。

At the very endof your settings.py, add this:

最后一刻你的settings.py的,补充一点:

try:
    from local_settings import *
except ImportError:
    pass

The try/except block is there so that Python just ignores the case when you haven't actually defined a local_settings file.

try/except 块在那里,因此当您尚未实际定义 local_settings 文件时,Python 只会忽略这种情况。

回答by janos

This is the best practice I think:

这是我认为的最佳实践:

  • local_settingsimports from settings
  • local_settingsoverrides settings specific to the local environment, especially DATABASES, SECRET_KEY, ALLOWED_HOSTSand DEBUGvariables
  • pass to django management commands the flag --settings=local_settings
  • local_settings从进口 settings
  • local_settings覆盖设置具体到当地的环境,尤其是DATABASESSECRET_KEYALLOWED_HOSTSDEBUG变量
  • 传递给 Django 管理命令标志 --settings=local_settings

You could implement local_settingslike this:

你可以这样实现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.
    }
}

A few additional key points:

补充几个关键点:

  • settings.pyis in version control, written in a way such that it's ready to use by contributors
  • local_settings.py(or more commonly prod_settings.py) is NOT in version control, and used in production by specifying --settings=prod_settingsor similar.
  • settings.py处于版本控制中,以一种可供贡献者使用的方式编写
  • local_settings.py(或更常见prod_settings.py)不在版本控制中,并通过指定--settings=prod_settings或类似方式在生产中使用。

Touching the stock settings file as little as possible also makes it easier to upgrade your django version. When you upgrade Django to the next version, look at the diff in the stock settings.pyand yours, and take actions as necessary depending on what changed. Changes in the default values can be important, and the less you touched the original settings.pyfile, the easier it will be to discern upstream changes.

尽可能少地接触库存设置文件也可以更轻松地升级您的 django 版本。当您将 Django 升级到下一个版本时,请查看库存settings.py和您的库存中的差异,并根据发生的变化采取必要的措施。默认值的更改可能很重要,您接触原始settings.py文件的次数越少,识别上游更改就越容易。

回答by John Mee

Since the topic resurfaces routinely let me summarise why you might want to consider this approach:

由于该主题经常出现,让我总结一下您可能想要考虑这种方法的原因:

  • a dumb settings file is very fast and easy to change; especially in a production environment. No python required: any idiot can jump in and change the database password in a file which just lists names and values; especially compared to a complex python settings file full of mysterious dangerous BIGCAPS names.

  • the application settingsshould be completely separated from the application code. You can put a config.ini outside the repository root and never again worry about a repo pull clobbering your settings, or your personal settings polluting the repo, or that clever code in your settings.py not making it into the repo to everyone else's advantage.

  • 愚蠢的设置文件非常快速且易于更改;尤其是在生产环境中。不需要python:任何白痴都可以在一个只列出名称和值的文件中修改数据库密码;特别是与充满神秘危险 BIGCAPS 名称的复杂 python 设置文件相比。

  • 应用程序settings应该与应用程序完全分离code。您可以将 config.ini 放在存储库根目录之外,再也不用担心 repo pull 破坏您的设置,或者您的个人设置污染了 repo,或者您的 settings.py 中的聪明代码没有将其放入 repo 对其他人有利.

This won't apply to small projects, but on bigger projects I've concluded that the local_settings strategy just doesn't cut it; over time enough application programming creeps in that it gets hard to handle; primarily as settings become derivative and/or codependent. There can be good justifications for settings to react according to the local settings which forces the import of a local_settingsfile to creep up toward the middle of settings.py. I find things start to get messy as that happens.

这不适用于小型项目,但在较大的项目中,我得出的结论是 local_settings 策略并不能解决问题;随着时间的推移,足够的应用程序编程变得难以处理;主要是因为设置变得衍生和/或相互依赖。设置根据本地设置做出反应可能有很好的理由,这会迫使local_settings文件的导入向settings.py. 我发现事情开始变得混乱。

My current solution is to use a configfile, I dub it "local.ini". It holds only those values which do actually change between deployed instances. There is no code: they are just values and booleans:

我目前的解决方案是使用一个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

With this in place I can treat the settings.pylike any other piece of application code: tweak it, check it in, and deploy it without having to worry about testing against whatever code might be lurking in a local_settings python code. My settings.pyis free of race conditions that come up when later settings depend on local settings, and I can switch features on and off writing easy-to-follow linear code. No more hurriedly tweaking the local_settings file when I've forgotten to add some new value, and no more daves_local_settings.pyand bobs_local_settings.pyfiles creeping into the repository.

有了这个,我可以settings.py像对待任何其他应用程序代码一样对待它:调整它、检入它并部署它,而不必担心针对可能潜伏在 local_settings python 代码中的任何代码进行测试。settings.py当以后的设置取决于本地设置时,我没有出现竞争条件,我可以打开和关闭功能,编写易于遵循的线性代码。没有更多的匆匆扭捏LOCAL_SETTINGS文件时,我忘记添加一些新的价值,并没有更多的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'

If you encounter a BOFH, like I had on one occasion, he got particularly excited about the ability to stick the local.iniinto the /etcdirectory as /etc/ourapp.iniand so keep the application directory itself a pure repository export. Sure you could do that with a local_settings.py but the last thing he wanted to do was mess with python code. A simple config file he could handle.

如果遇到BOFH,就像我曾有一次,他得到了特别兴奋粘能力local.ini进入/etc的目录/etc/ourapp.ini,因此保持应用程序目录本身纯仓库出口。当然你可以用 local_settings.py 做到这一点,但他最不想做的就是弄乱 python 代码。他可以处理的简单配置文件。

回答by Siddhesh Suthar

Before running the server do

在运行服务器之前做

export DJANGO_SETTINGS_MODULE=your_app_name.local_settings where your_app_name should be replaced by your App's name. And don't forget to do

export DJANGO_SETTINGS_MODULE=your_app_name.local_settings 其中 your_app_name 应替换为您的应用程序名称。并且不要忘记做

from settings import *

in your local_settings.py file

在您的 local_settings.py 文件中

回答by Yeo

I kept a copy of __local_settings.py:

我保留了一份__local_settings.py

  • local_settings.pyis being ignored in the version control, but not __local_settings.py
  • update README.mdto inform the team on how to setup: cp {__,}local_settings.py(which make a copy for their local_settings)
  • local_settings.py在版本控制中被忽略,但不是 __local_settings.py
  • 更新README.md以通知团队如何设置:(cp {__,}local_settings.py为他们的 local_settings 创建一个副本)

In the past

在过去

I used to import those settings.

我曾经导入这些设置。

# settings.py
DATABASE = {...}

try:
    from .local_settings import *
except ImportError:
    pass

now

现在

I just import the settings itself from the local_settings.py.

我只是从local_settings.py.

And with the following command: python manage.py runserver --settings=<proj>.local_settings.

并使用以下命令:python manage.py runserver --settings=<proj>.local_settings.

# local_settings.py & __local_settings.py
from .settings import *

DATABASE = {...}

And since, I usually don't interact with manage.pydirectly, because some parameters are explicitly necessary for me, (e.g. address:port). Therefore, I put all of those command into my Makefile.

因为,我通常不manage.py直接与之交互,因为某些参数对我来说是明确必需的,(例如address:port)。因此,我将所有这些命令放入我的Makefile.

For example, here's my Makefile:

例如,这是我的 Makefile:

run:
    python manage.py runserver 0.0.0.0:8000 --settings=<proj>.local_settings

sh:
    python manage.py shell_plus --settings=<proj>.local_settings

dep:
    npm install
    pip install -r requirements.txt

Thus:

因此:

make dep
make sh 
make run

Conclusion

结论

Provided that you are notusing Makefileas your workflow, then you may use the earlier method, but if you are using makefile, then i believe it is better to be more explicit in your Makefile.

如果您使用Makefile作为您的工作流程,那么您可以使用较早的方法,但如果您使用的是 makefile,那么我认为最好在您的 Makefile 中更加明确。

回答by Darex1991

I found the similar solution. This is my configuration for this case:

我找到了类似的解决方案。这是我对这种情况的配置:

settings.py:

设置.py:

DEBUG = False

try:
    from local_settings import *

except ImportError:
    pass

if DEBUG is False:
    ALLOWED_HOSTS = ['sth.com']
    DATABASES = {
        ....
    }

local_settings.py:

local_settings.py:

from settings import *
ALLOWED_HOSTS = ['*']
DEBUG = True
DATABASES = {
    ...
}

回答by Eugene Yarmash

Yet another approach is to use python-dotenvand environment variables to customize settings for different environments.

另一种方法是使用python-dotenv环境变量来自定义不同环境的设置。

Create the .envfile along-side your settings.py:

.env您的settings.py:一起创建文件:

# .env
SECRET_KEY=your-secret-key
DATABASE_PASSWORD=your-database-password

Add the following code to your settings.py:

将以下代码添加到您的settings.py

# settings.py
from dotenv import load_dotenv
load_dotenv()

# OR, explicitly providing path to '.env'
from pathlib import Path  # python 3.4+
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

At this point, parsed keys/values from the .envfile are present as environment variables and they can be conveniently accessed via os.getenv():

此时,.env文件中解析的键/值作为环境变量存在,可以通过以下方式方便地访问os.getenv()

# settings.py
import os
SECRET_KEY = os.getenv('SECRET_KEY')
DATABASE_PASSWORD = os.getenv('DATABASE_PASSWORD')   

回答by Holovin

Add this to the end of the file settings.py

将此添加到文件 settings.py 的末尾

try:
    from .local_settings import *
except ImportError:
    pass

And create file local_settings.py with your new settings for example

并使用您的新设置创建文件 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.
    }
}