Django에서 로컬 및 프로덕션 설정을 관리하는 방법은 무엇입니까?


298

로컬 개발 및 프로덕션 서버의 설정을 처리하는 데 권장되는 방법은 무엇입니까? 상수 등의 일부는 변경하거나 액세스 할 수 있지만 정적 파일 경로와 같은 일부는 다르게 유지해야하므로 새 코드가 배포 될 때마다 덮어 쓰지 않아야합니다.

현재 모든 상수를 추가하고 있습니다. settings.py 있습니다. 그러나 로컬에서 일부 상수를 변경할 때마다 프로덕션 서버에 복사하고 프로덕션 특정 변경 사항을 위해 파일을 편집해야합니다 ... :(

편집 :이 질문에 대한 표준 답변이없는 것 같습니다. 가장 인기있는 방법을 수락했습니다.



django-configurations를 살펴보십시오 .
JJD

2
허용되는 방법은 더 이상 가장 인기있는 방법이 아닙니다.
Daniel

2
장고 분할 설정 은 사용하기가 매우 쉽습니다. 기본 설정을 다시 쓰지 않아도됩니다.
sobolevn

yo. base.py 파일과 local.py "from .base import *"에서 production.py ".base import *"와 동일해야합니다. python manage.py runserver- settings = project_name.settings.local
Roberth Solís

답변:


127

에서 settings.py:

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

필요한 것을 무시할 수 있습니다 local_settings.py. 그런 다음 버전 관리를 벗어나야합니다. 그러나 복사에 대해 언급 했으므로 아무것도 사용하지 않는 것 같습니다.)


3
새로운 설정을 쉽게 추적 / 배포하려면 프로덕션 / 테스트 머신에서 "local_settings.py"를 사용하고 개발에서는 사용하지 마십시오.
John Mee

8
이것이 내가하는 방식입니다
-settings.py

61
이 접근 방식은 개발 및 프로덕션에서 버전없는 코드가 실행되고 있음을 의미합니다. 그리고 모든 개발자는 다른 코드 기반을 가지고 있습니다.
pydanny

8
@pydanny 문제는 Django가 .py 파일에 구성을 저장한다는 것입니다. 모든 개발자와 프로덕션 서버가 동일한 설정을 사용할 것으로 기대할 수 없으므로이 .py 파일을 변경하거나 대체 솔루션 (.ini 파일, 환경 등)을 구현해야합니다.
Tupteq

3
알파벳 폴더 목록 으로 그룹화하는 settings_local대신 모듈 을 호출하는 local_settings것이 settings.py좋습니다. 자격 증명이 Git에 속하지 않으므로 settings_local.py버전 관리를 유지하십시오 .gitignore. 우연히 오픈 소싱을 상상해보십시오. settings_local.py.txt대신 git라는 템플릿 파일을 유지 합니다.
줄 바꿈

297

Django의 두 가지 특종 : 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

이 책의 저자 는 샘플 프로젝트 레이아웃 템플릿도 작성했습니다. Github에 을 .


62
--settings매번 사용하는 대신 DJANGO_SETTINGS_MODULEenvvar를 설정할 수 있습니다. 이것은 예를 들어 Heroku와 잘 작동합니다 : 전역 적으로 프로덕션으로 설정 한 다음 .env 파일의 dev로 재정의하십시오.
Simon Weber

9
DJANGO_SETTINGS_MODULESimon에게 env var를 사용 하는 것이 가장 좋습니다.
kibibu

20
다음과 같이 BASE_DIR설정 을 변경해야 할 수도 있습니다.os.path.dirname(os.path.realpath(os.path.dirname(__file__) + "/.."))
Petr Peller

5
django 문서에 따라 @rsp from django.conf import settings, 인터페이스를 추상화하고 설정 위치에서 코드를 분리하는 객체 인 docs.djangoproject.com/en/dev/topics/settings/…

3
환경 변수를 통해 DJANGO_SETTINGS_MODULE을 설정 한 경우에도 wsgi.py 파일에 os.environ.setdefault ( "DJANGO_SETTINGS_MODULE", "projectname.settings.production")가 필요합니까? 또한 export DJANGO_SETTINGS_MODULE = projectname.settings.local을 사용하여 환경 변수를 설정했지만 터미널을 닫을 때 손실됩니다. 저장되도록하려면 어떻게해야합니까? 그 줄을 bashrc 파일에 추가해야합니까?
Kritz

71

대신 settings.py이 레이아웃을 사용하십시오.

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py 대부분의 구성이있는 곳입니다.

prod.py 공통의 모든 것을 가져오고 재정의 해야하는 모든 것을 재정의합니다.

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

마찬가지로 dev.py모든 항목을 가져 common.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. 대부분의 구성은 한 곳에 common.py있습니다.
  3. 생산물에 특정한 것들이 들어가고 prod.py, 실체에 특정한 것들이 들어갑니다 dev.py. 간단 해.
  4. 당신은에서 물건을 무시할 수 있습니다 common.py에서 prod.py또는 dev.py, 당신은 아무것도를 대체 할 수 있습니다__init__.py .
  5. 간단한 파이썬입니다. 다시 가져 오기 해킹이 없습니다.

2
여전히 설정 파일의 project.wsgi 및 manage.py 파일에서 무엇을 설정 해야하는지 알아 내려고 노력 중입니다. 이것에 약간의 빛을 비출 것입니까? 특히, manage.py 파일에서 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings")foobar는 __init__.py파일이있는 폴더이고 설정은 __init__.py비밀이 포함 된 파일 이있는 폴더이며 dev.py를 가져 와서 common.py를 가져옵니다. 편집 신경 쓰지 마라. 필요한 모듈이 설치되어 있지 않았다. 내 잘못이야! 이것은 잘 작동합니다!
teewuane

5
두 가지 : 1) prod.py에서 = False보다는 dev.py에서 Debug = True를 설정하는 것이 좋습니다. 2) init .py로 전환하는 대신 DJANGO_SETTINGS_MODULE 환경 변수를 사용하여 전환하십시오. 이는 PAAS 배포 (예 : Heroku)에 도움이됩니다.
Rob Grant

django 1.8.4 에서이 설정을 사용하고 runserver를 시도하면 "django.core.exceptions.ImproperlyConfigured : SECRET_KEY 설정이 비어 있으면 안됩니다."라는 메시지가 표시됩니다. 심지어 init .py 파일 에 SECRET_KEY가 있습니다. 뭔가 빠졌습니까?
polarcare

AWS_SECRET_ACCESS_KEY = os.getenv ( "AWS_SECRET_ACCESS_KEY") 와 같은 것을 사용하는 것이 더 안전하지 않습니까? 정직한 질문-왜 버전을 원하지 않는지 알고 있지만 다른 대안은 환경에서 가져 오는 것입니다. 물론 환경 변수 설정에 대한 의문을 제기하지만 배포 메커니즘에 맡길 수 있습니까?
JL Peyret

20

Harper Shelby가 게시 한 "if DEBUG"스타일 설정의 약간 수정 된 버전을 사용합니다. 분명히 환경 (win / linux / etc.)에 따라 코드를 약간 조정해야 할 수도 있습니다.

과거에는 "DEBUG 인 경우"를 사용했지만 DEUBG를 False로 설정하여 테스트해야하는 경우가 있음을 알게되었습니다. 환경이 생산 또는 개발인지 구분하기를 원했기 때문에 DEBUG 수준을 자유롭게 선택할 수있었습니다.

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 설정 파일 방법을 사용하지 않았습니다).


이것이 실제 코드 파일 인 Django의 설정이 허용하는 종류이며 힌트입니다. 나는 이런 식으로 아무것도하지 않았지만 분명히 내 것보다 더 나은 일반적인 대답 일 수있는 일종의 해결책입니다.
Harper Shelby

3
방금 처음 으로이 문제를 해결하고 약간의 차이와 함께 솔루션을 사용하기로 결정했습니다. 따라서 사용하는 os.environ 테스트 대신 uuid.getnode () == 12345678901 (실제로 다른 숫자)인지 테스트하고 있습니다. os.environ [ 'COMPUTERNAME']이 (가) 컴퓨터마다 고유하다는 것을 확신시키는 문서를 찾을 수 없습니다.
Joe Golton

os.environ [ 'COMPUTERNAME']은 Amazon AWS Ubuntu에서 작동하지 않습니다. KeyError가 발생합니다.
nu everest

UUID를 사용할 때이 솔루션은 나에게 가장 좋고 간단한 것으로 입증되었습니다. 복잡하고 지나치게 모듈화 된 패치 워크가 많이 필요하지 않습니다. 프로덕션 환경에서는 데이터베이스 비밀번호와 SECRET_KEY를 버전 제어 외부에있는 별도의 파일에 배치해야합니다.
nu everest

os.environ['COMPUTERNAME']불행히도 PythonAnywhere에서는 작동하지 않습니다. KeyError가 발생합니다.
nbeuchat

14

settings_local.py와 settings_production.py를 사용합니다. 몇 가지 옵션을 시도한 후 두 개의 설정 파일을 갖는 것이 쉽고 빠르면 복잡한 솔루션으로 시간을 낭비하는 것이 쉽다는 것을 알았습니다.

Django 프로젝트에 mod_python / mod_wsgi를 사용할 때는 설정 파일을 가리켜 야합니다. 로컬 서버의 app / settings_local.py 및 프로덕션 서버의 app / settings_production.py를 가리키면 인생이 쉬워집니다. 적절한 설정 파일을 편집하고 서버를 다시 시작하십시오 (Django 개발 서버가 자동으로 다시 시작됨).


2
로컬 개발 서버는 어떻습니까? django 웹 서버 (을 사용하여 실행 python manage.py runserver)에 사용할 설정 파일을 알려주는 방법이 있습니까?
akv

2
@akv runserver 명령 끝에 --settings = [모듈 이름] (. py 확장자 없음)을 추가하면 사용할 설정 파일을 지정할 수 있습니다. 그렇게하려면 개발 설정이 구성된 쉘 스크립트 / 배치 파일을 작성하십시오. 날 믿어, 네 손가락이 고마워 할거야
T. Stone

이것이 내가 사용하는 솔루션입니다. 프로덕션 또는 개발에 모두 사용할 설정 파일을 해킹하는 것은 지저분합니다.
George Godik

4
나는 당신이 항상 그것을 지정할 필요가 없기 때문에 개발에서 settings.py를 사용하는 것이 더 좋다고 생각합니다.
Andre Bossard

이 방법으로 프록시 django.conf.settings를 통해 설정 모듈을 가져와야한다고 가정합니까? 그렇지 않으면 라이브 푸시시 올바른 설정 파일을 가리 키도록 가져 오기 선언을 편집해야합니다.
Groady

8

TL; DR : 트릭을 수정하는 것입니다 os.environment당신이 가져 오기 전에 settings/base.py어떤에서 settings/<purpose>.py이 크게 일을 단순화합니다.


이 모든 얽힌 파일에 대해 생각하면 두통이 생깁니다. DEBUG나중에 설정이 변경된 경우에 이미 설정 한 내용의 조합, 가져 오기 (조건에 따라), 재정의, 패치 악몽이야!

몇 년 동안 나는 모든 다른 솔루션을 겪었습니다. 그들은 모두 다소 효과가 있지만 관리하기가 너무 고통 스럽습니다. WTF! 번거 로움이 정말로 필요한가? 하나의 settings.py파일로 시작했습니다 . 이제이 모든 것을 올바른 순서로 올바르게 결합하기위한 문서가 필요합니다!

나는 마침내 아래 해결책으로 (내) 달콤한 자리에 도달하기를 바랍니다.

목표를 되짚어 봅시다 (일부 공통, 일부 내)

  1. 비밀을 비밀로 유지하십시오. 리포지토리에 저장하지 마십시오!

  2. 12 요인 스타일 환경 설정을 통해 키와 비밀을 설정 / 읽습니다 .

  3. 적절한 대체 기본값이 있습니다. 이상적으로는 로컬 개발을 위해 기본값 이외의 다른 것이 필요하지 않습니다.

  4. … 기본 생산을 안전하게 유지하십시오. 프로덕션 환경에서 안전한 기본 설정을 기억해야하는 것보다 로컬에서 설정 재정의를 놓치는 것이 좋습니다.

  5. 전환 할 수있는 기능이 DEBUG다른 설정에 영향을 줄 수있는 방법에 온 / 오프 (예. 압축 된 자바 스크립트를 사용하여 여부를).

  6. 로컬 / 테스트 / 스테이징 / 프로덕션과 같은 목적 설정 간 전환은을 기반으로해야합니다 DJANGO_SETTINGS_MODULE.

  7. …와 같은 환경 설정을 통해 추가 매개 변수화를 허용 DATABASE_URL합니다.

  8. … 또한 서로 다른 목적 설정을 사용하고 로컬로 나란히 실행할 수 있습니다 (예 : 로컬 개발자 시스템의 프로덕션 설정, 프로덕션 데이터베이스에 액세스하거나 연기 테스트 압축 스타일 시트.

  9. 특히 프로덕션 환경에서 환경 변수가 명시 적으로 설정되지 않으면 (최소한 빈 값이 필요함) 실패합니다. EMAIL_HOST_PASSWORD.

  10. django-admin startprojectDJANGO_SETTINGS_MODULE 중 manage.py의 기본 설정에 응답

  11. 조건이있는 경우, 최소한으로 조건문을 유지 목적의 환경 유형 (예를 들면. 생산 세트의 로그 파일과의 회전), 관련 목적의 설정 파일에서 재정의 설정.

하지마

  1. django가 파일에서 DJANGO_SETTINGS_MODULE 설정을 읽지 못하게하십시오.
    어! 이것이 메타인지 생각하십시오. docker env와 같은 파일이 필요한 경우 django 프로세스를 시작하기 전에 환경에서 파일을 읽으십시오.

  2. 프로젝트 / 앱 코드에서 DJANGO_SETTINGS_MODULE을 재정의하지 마십시오 (예 : 호스트 이름 또는 프로세스 이름을 기반으로합니다.
    환경 변수를 설정하는 것이 게으른 경우 (예 :와 같이 setup.py test) 프로젝트 코드를 실행하기 직전에 툴링에서 환경 변수를 설정 하십시오.

  3. django가 설정을 읽는 방법의 마법과 패치를 피하고 설정을 사전 처리하지만 나중에 방해하지는 마십시오.

  4. 복잡한 논리 기반 넌센스가 없습니다. 구성은 즉시 계산되지 않고 수정되고 구체화되어야합니다. 대체 기본값을 제공하는 것만으로도 충분한 논리입니다.
    로컬에서 올바른 설정 세트를 사용하지만 원격 서버, 수백 대의 머신 중 하나에서 다르게 계산 된 이유는 무엇입니까? 오! 단위 테스트? 설정? 진심이야?

해결책

내 전략은 우수한 구성 장고-와 환경 에 사용 ini스타일 파일, 제공 os.environment지역 개발에 대한 기본값을, 최소한의 짧은 settings/<purpose>.py을 가진 파일 import settings/base.py 후에os.environment에서 설정 INI파일. 이것은 효과적으로 일종의 설정 주입을 제공합니다.

여기서 트릭은 os.environment가져 오기 전에 수정하는 것 settings/base.py입니다.

전체 예제를 보려면 repo를 수행하십시오. https://github.com/wooyek/django-settings-strategy

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

설정 /.env

로컬 개발의 기본값입니다. 주로 필요한 환경 변수를 설정하는 비밀 파일. 로컬 개발에 필요하지 않은 경우 빈 값으로 설정하십시오. 우리는 여기서 기본값을 제공 settings/base.py하며 환경에서 누락 된 경우 다른 시스템에서 실패 하지 않습니다 .

settings / local.py

여기서 발생하는 일은에서 환경을로드 settings/.env한 다음에서 공통 설정을 가져 오는 것입니다 settings/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

settings / production.py

프로덕션 환경에서는 환경 파일을 기 대해서는 안되지만 무언가를 테스트하는 경우 환경 파일이 더 쉽습니다. 그러나 어쨌든 최소한의 인라인 설정을 제공하지 않으므로 settings/base.py그에 따라 응답 할 수 있습니다.

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

관심의 주요 포인트는 여기에 있습니다 DEBUGASSETS_DEBUG재 지정, 그들은 파이썬에 적용됩니다 os.environ들이 환경과 파일에서 누락 된 경우에만.

이것들은 프로덕션 기본값이 될 것이며, 환경이나 파일에 넣을 필요는 없지만 필요한 경우 재정의 할 수 있습니다. 산뜻한!

settings / base.py

이것들은 대부분 바닐라 장고 설정이며, 몇 가지 조건부와 환경에서 많은 것을 읽습니다. 거의 모든 것이 여기에 있으며, 모든 목적 환경을 일관되고 유사하게 유지합니다.

주요 차이점은 다음과 같습니다 (자기 설명이 필요합니다).

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',)

마지막 비트는 여기에 힘을 보여줍니다. ASSETS_DEBUG합리적인 기본값을 가지고 있으며 settings/production.py, 환경 설정에 의해 재정의 될 수 있고 심지어 재정의 될 수도 있습니다! 예이!

사실상 우리는 중요한 계층 구조를 가지고 있습니다 :

  1. settings / .py-목적에 따라 기본값을 설정하고 비밀을 저장하지 않습니다
  2. settings / base.py-대부분 환경에 의해 제어됩니다
  3. 공정 환경 설정-12 단계 베이비!
  4. settings / .env-쉬운 시작을위한 로컬 기본값

야누스 .. 그래서 .env 파일에 모든 API 키와 인증 키 및 암호 등이 있습니까? TWILLIO_API = "abc123"처럼? 또는 TWILLIO_API = env ( "TWILLIO_API")?
dbinott

예, 그러나 이것은 환경 설정의 대체입니다. 이 파일은 개발에 유용하지만 환경 설정 또는 서버 프로세스에 대한 환경 설정을 엄격하게 설정하는 해당 플랫폼을 엄격하게 사용해야하는 저장소에 저장되거나 프로덕션으로 푸시되지 않습니다.
야누스 스 코니 에츠 니

7

django-split-settings 의 도움으로 구성을 관리합니다 .

기본 설정을 대체합니다. 간단하지만 구성 할 수 있습니다. 기존 설정을 리팩토링 할 필요가 없습니다.

다음은 작은 예입니다 (file 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()
    )

그게 다야.

최신 정보

의 설정 관리에 대한 블로그 게시물을 작성했습니다 . 보세요!djangodjango-split-sttings


1
나는 그것을 시도했다 .. 일단 장고 단위 테스트를 실행하려고 시도했을 때 벽에
부딪쳤다

내가 당신을 위해 요점을 만들었습니다 : gist.github.com/sobolevn/006c734f0520439a4b6c16891d65406c
sobolevn

내가 좋아하는 뭔가있어 내가 물건을 가져 싶으면 내가 아는하기 위해 settings.DEBUG 플래그를 확인 그래서 .. 그 플래그가 항상 (참조 장고 단위 테스트에서 false로 설정되어, 내 코드에 여기에 내 작품이 주위에 그들을 무시하는 것입니다 그래서) 같은 각 테스트는 지금
abbood

여기에 또 다른 질문이 있습니다 : 내 uwsgi.ini파일은 dev / prod마다 다른 설정을 가지고 있습니다. 내 설정 파일에서 값을 선택하는 방법에 대한 아이디어가 있습니까?
abbood

죄송합니다. 설정이 없습니다. 더 자세한 내용으로 별도의 질문을 할 수 있으며 도와 드리겠습니다.
sobolevn

6

이러한 솔루션의 대부분의 문제점은 로컬 설정을 공통 설정 이전 또는 이후에 적용 한다는 것입니다.

따라서 다음과 같은 것을 재정의하는 것은 불가능합니다.

  • env 특정 설정은 memcached 풀의 주소를 정의하고 기본 설정 파일에서이 값은 캐시 백엔드를 구성하는 데 사용됩니다
  • 환경 별 설정은 기본 설정에 앱 / 미들웨어를 추가하거나 제거합니다.

동시에.

ConfigParser 클래스와 함께 "ini"스타일 구성 파일을 사용하여 하나의 솔루션을 구현할 수 있습니다. 여러 파일, 게으른 문자열 보간, 기본값 및 기타 많은 기능을 지원합니다. 여러 파일이로드되면 더 많은 파일을로드 할 수 있으며 해당 파일의 값은 이전 파일보다 우선합니다.

머신 주소, 환경 변수 및 이전에로드 한 구성 파일의 값에 따라 하나 이상의 구성 파일을로드합니다. 그런 다음 구문 분석 된 값을 사용하여 설정을 채 웁니다.

내가 성공적으로 사용한 전략은 다음과 같습니다.

  • 기본 defaults.ini파일 로드
  • 컴퓨터 이름을 확인하고 짧은 경기에서 가장 긴 일치 (그래서, 내가로드에, 반전 FQDN과 일치하는 모든 파일을로드 net.ini한 후 net.domain.ini, 다음 net.domain.webserver01.ini, 각각의 가능성이 이전의 값을 무시). 이 계정은 개발자 컴퓨터에도 적용되므로 로컬 개발을 위해 각자 선호하는 데이터베이스 드라이버 등을 설정할 수 있습니다.
  • "클러스터 이름"이 선언되어 있는지 확인하고이 경우 cluster.cluster_name.ini데이터베이스 및 캐시 IP와 같은 것을 정의 할 수있는 load입니다 .

이를 통해 달성 할 수있는 일의 예로, env 당 "하위 도메인"값을 정의 할 수 있습니다. 그런 다음 기본 설정 ( hostname: %(subdomain).whatever.net)에서 장고가 작동하는 데 필요한 모든 호스트 이름과 쿠키를 정의합니다.

이것은 내가 얻을 수있는 것처럼, 대부분의 (기존) 파일에는 3 또는 4 개의 설정 만 있습니다. 이 외에도 고객 구성을 관리해야했기 때문에 데이터베이스 이름, 사용자 및 암호, 할당 된 하위 도메인 등과 같은 추가 구성 파일 세트가 고객 당 하나 이상 존재했습니다.

필요에 따라이 값을 낮게 또는 높게 조정할 수 있습니다. 환경별로 구성하려는 키를 구성 파일에 넣고 새 구성이 필요하면 이전 값을 기본 구성에 넣고 무시하십시오. 필요한 곳에.

이 시스템은 신뢰성이 입증되었으며 버전 제어와 잘 작동합니다. sysadmin의 분위기에 따라 클러스터의 크기와 멤버가 변경되는 50 명 이상의 고객으로 두 개의 개별 애플리케이션 클러스터 (시스템 당 django 사이트의 15 개 이상의 개별 인스턴스)를 오랫동안 관리하는 데 사용되었습니다. .


1
ini에서 Django의 설정으로 설정을로드하는 방법에 대한 예가 있습니까?
kaleissin

docs.python.org/2/library/configparser.html을 참조하십시오 . 파서를로드 한 config = ConfigParser.ConfigParser() 다음 파일을 읽고를 config.read(array_of_filenames)사용하여 값을 얻을 수 있습니다 config.get(section, option). 따라서 먼저 구성을로드 한 다음 구성 값을 사용하여 설정 값을 읽습니다.
다시 작성

5

나는 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

아마도 이런 것이 도움이 될 것입니다.


4

settings.py는 라이브 코드 파일입니다. 프로덕션에 DEBUG가 설정되어 있지 않다고 가정하면 (최상의 방법 임) 다음과 같은 작업을 수행 할 수 있습니다.

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

꽤 기본적이지만 이론적으로 DEBUG의 값 또는 사용하려는 다른 변수 또는 코드 검사를 기반으로 복잡한 수준까지 올라갈 수 있습니다.


4

대부분의 프로젝트에서 다음 패턴을 사용합니다.

  1. 모든 환경에 공통적 인 설정을 저장하는 settings_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 )


3

그 문제에 대한 나의 해결책은 여기에 이미 언급 된 몇 가지 해결책의 혼합입니다.

  • 나는 dev와 prod에 local_settings.py내용이 있는 파일을 유지합니다.USING_LOCAL = TrueUSING_LOCAL = False
  • 에서 settings.py내가 그 파일 가져 오기를 수행 얻기 위해 USING_LOCAL설정을

그런 다음 모든 환경 종속 설정을 그 기반으로합니다.

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

이 설정을 여러 파일에 분산시키는 것보다 단일 파일로 구성을 쉽게 유지할 수 있기 때문에 유지 관리해야하는 두 개의 별도 settings.py 파일을 사용하는 것이 좋습니다. 이와 같이 설정을 업데이트 할 때 두 환경 모두에서 설정을 수행하는 것을 잊지 않습니다.

물론 모든 방법에는 단점이 있으며이 방법도 예외는 아닙니다. 여기서 문제는 local_settings.py변경 사항을 프로덕션으로 푸시 할 때마다 파일을 덮어 쓸 수 없다는 것입니다. 즉 , 모든 파일을 맹목적으로 복사 할 수는 없지만 그와 함께 살 수있는 것입니다.


3

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)

기본적으로 각 컴퓨터 (개발 또는 프로덕션)에는 동적으로로드되는 적절한 hostname_settings.py 파일이 있습니다.



3

1-앱 내에 새 폴더를 만들고 이름을 설정하십시오.

2-이제 __init__.py그 안에 새 파일을 작성하십시오.

from .base import *

try:
    from .local import *
except:
    pass

try:
    from .production import *
except:
    pass

3-설정 폴더 이름 local.pyproduction.py및 에 새 파일 3 개를 만듭니다 base.py.

4-내부 base.py에서 이전 settings.py폴더 의 모든 내용을 복사 하고 다른 이름으로 바꾸십시오 old_settings.py.

5-base.py에서 새로운 설정 경로를 가리 키도록 BASE_DIR 경로를 변경하십시오.

오래된 길-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

새로운 길-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

이러한 방식으로 프로젝트 디렉토리를 구성하고 생산 및 로컬 개발간에 관리 할 수 ​​있습니다.


2

settings다른 환경에서 다른 구성 을 사용하려면 다른 설정 파일을 작성하십시오. 그리고 배포 스크립트에서 --settings=<my-settings.py>매개 변수를 사용하여 서버를 시작하면 다른 환경에서 다른 설정 을 사용할 수 있습니다 .

이 방법을 사용하면 다음과 같은 이점이 있습니다 .

  1. 각 환경에 따라 설정이 모듈화됩니다.

  2. master_settings.py에서 기본 구성 이 포함 된 가져 오기를 environmnet_configuration.py가져와 해당 환경에서 변경하려는 값을 무시할 수 있습니다.

  3. 대규모 팀이있는 경우 각 개발자는 local_settings.py서버 구성을 수정할 위험없이 코드 리포지토리에 추가 할 수있는 자체 개발자를 보유 할 수 있습니다. 당신은 이러한 로컬 설정을 추가 할 수 있습니다 .gitnore당신이 사용하는 경우 자식을 하거나 .hginore만약 당신이 의욕 에 대한 버전 제어 (또는 다른). 이렇게하면 로컬 설정이 실제 코드베이스의 일부가 아니어도 깨끗하게 유지됩니다.


2

설정을 다음과 같이 나누었습니다.

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

우리는 3 가지 환경을 가지고 있습니다

  • dev
  • 각색
  • 생산

이제 스테이징과 프로덕션은 가능한 최대의 유사한 환경을 가져야합니다. 그래서 우리는 prod.py둘 다 유지 했습니다.

그러나 실행중인 서버가 프로덕션 서버임을 식별 해야하는 경우가있었습니다. @티. Stone의 답변은 다음과 같이 수표를 작성하는 데 도움이되었습니다.

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  

1

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)

설정 파일 내부에서 많은 if를 수행하는 대신 설정 파일을 두 개의 별도 파일로 분리하는 것이 더 쉽다는 것을 알았습니다.


1

삭제하는 경우 다른 파일을 유지하는 대안으로 : git 또는 다른 VCS를 사용하여 로컬에서 서버로 코드를 푸시하는 경우 설정 파일을 .gitignore에 추가하면됩니다.

이렇게하면 아무 문제없이 두 곳에서 서로 다른 내용을 가질 수 있습니다. 서버에서 SO의 독립 버전 버전을 구성 할 수 있으며 로컬에서 변경 한 내용은 서버에 반영되지 않으며 그 반대도 마찬가지입니다.

또한 github에서 settings.py 파일도 제거합니다. 큰 결함은 많은 초보자가하는 것을 보았습니다.



0

@ T가 최고의 솔루션을 제안한다고 생각합니다. 스톤,하지만 왜 장고에서 DEBUG 플래그를 사용하지 않는지 모르겠습니다. 내 웹 사이트에 아래 코드를 작성하십시오.

if DEBUG:
    from .local_settings import *

항상 간단한 솔루션이 복잡한 솔루션보다 낫습니다.


-2

나는 여기에 대한 답변이 매우 유용하다는 것을 알았습니다. (이것이 더 확실하게 해결 되었습니까? 마지막 응답은 1 년 전이었습니다.) 나열된 모든 접근법을 고려한 후 여기에 나열되지 않은 솔루션을 생각해 냈습니다.

내 기준은 다음과 같습니다.

  • 모든 것이 소스 제어에 있어야합니다. 나는 거짓말을하는 것을 좋아하지 않습니다.
  • 이상적으로는 하나의 파일에 설정을 유지하십시오. 내가 똑바로 보지 않으면 잊어 버립니다. :)
  • 배포 할 수동 편집이 없습니다. 단일 패브릭 명령으로 테스트 / 푸시 / 배포 할 수 있어야합니다.
  • 개발 설정을 프로덕션으로 유출하지 마십시오.
  • 가능한 한 "표준"(* 기침 *) 장고 레이아웃에 최대한 가깝게 유지하십시오.

호스트 컴퓨터의 스위치를 전환하는 것이 의미가 있다고 생각했지만 여기서 실제 문제는 환경 마다 다른 설정이며 다른 순간이 있다는 것을 알았습니다. 이 코드를 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'

이런 식으로 앱의 기본 설정은 프로덕션 설정으로, 개발 환경을 명시 적으로 "허용"합니다. 환경 변수가 다른 방법보다 로컬에 설정하는 것을 잊어 버리고 프로덕션 환경에서 무언가를 설정하고 일부 dev 설정을 사용하는 것을 잊어 버리는 것이 훨씬 안전합니다.

쉘이나 .bash_profile 또는 어디서나 로컬로 개발할 때 :

$ export DJANGO_DEVELOPMENT_SERVER=yep

(또는 Windows에서 개발하는 경우 제어판을 통해 설정하거나 요즘에 불리는 것을 ... Windows는 항상 환경 변수를 설정할 수 있도록 모호하게 만들었습니다.)

이 접근 방식을 사용하면 개발 설정이 모두 하나의 표준 위치에 있으며 필요한 경우 프로덕션 설정을 무시합니다. 개발 설정과 관련된 모든 문제는 프로덕션에 영향을 미치지 않으면 서 소스 제어를 수행하기 위해 완전히 안전해야합니다.


다른 구성 파일을 유지 관리하고 DJango 표준 env 변수 DJANGO_SETTINGS_MODULE을 사용하여 선택하는 것이 좋습니다
Rob Grant
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.