Django : 개발 및 프로덕션 설정을 관리하는 방법은 무엇입니까?


129

기본 앱을 개발하고 있습니다. 이제 배포 단계에서 로컬 설정과 프로덕션 설정이 모두 필요하다는 것이 분명해졌습니다.

다음을 아는 것이 좋습니다.

  • 개발 및 프로덕션 설정을 처리하는 가장 좋은 방법.
  • django-debug-toolbar와 같은 앱을 개발 환경에서만 유지하는 방법.
  • 개발 및 배포 설정에 대한 기타 팁과 모범 사례.

답변:


109

DJANGO_SETTINGS_MODULE환경 변수 설정 장고 파일 컨트롤이로드됩니다.

따라서 각 환경에 대해 별도의 구성 파일을 만들고 (물론 import *별도의 "공유 설정"파일에서 둘 다 가능함) 사용할 DJANGO_SETTINGS_MODULE것을 제어하는 ​​데 사용합니다.

방법은 다음과 같습니다.

Django 문서에서 언급했듯이 :

DJANGO_SETTINGS_MODULE의 값은 Python 경로 구문 (예 : mysite.settings)이어야합니다. 설정 모듈은 Python 가져 오기 검색 경로에 있어야합니다.

자, 사용자가 만든 가정하자 myapp/production_settings.pymyapp/test_settings.py소스 저장소에.

이 경우 각각 DJANGO_SETTINGS_MODULE=myapp.production_settings전자 DJANGO_SETTINGS_MODULE=myapp.test_settings를 사용하고 후자를 사용하도록 설정합니다.


여기서부터 문제는 DJANGO_SETTINGS_MODULE환경 변수 설정으로 귀결됩니다 .

DJANGO_SETTINGS_MODULE스크립트 또는 셸을 사용하여 설정

그런 다음 부트 스트랩 스크립트 또는 프로세스 관리자를 사용하여 환경을 설정하여 올바른 설정을로드하거나 Django를 시작하기 전에 쉘에서 실행할 수 있습니다 export DJANGO_SETTINGS_MODULE=myapp.production_settings..

이 내보내기는 쉘에서 언제든지 실행할 수 있습니다 .bashrc. 사용자 또는 다른 곳에있을 필요는 없습니다 .

DJANGO_SETTINGS_MODULE프로세스 관리자를 사용하여 설정

환경을 설정하는 부트 스트랩 스크립트를 작성하는 것을 좋아하지 않는 경우 (그리고 그렇게 느끼는 데에는 매우 좋은 이유가 있습니다!) 프로세스 관리자를 사용하는 것이 좋습니다.


마지막으로, 주 당신은 할 수 의 장점을 PYTHONPATH(에 저장, 프로덕션 서버에서 예를 들어, 완전히 다른 위치에 설정을 저장하는 변수 /etc/). 이를 통해 애플리케이션 파일에서 구성을 분리 할 수 ​​있습니다. 원할 수도 있고 원하지 않을 수도 있으며 앱의 구조에 따라 다릅니다.


7
명확히하기 위해 settings.py파일은 SiteName/settings.py기본적으로 저장 되기 때문에 동일한 디렉토리에 대체 설정 파일을 배치하면 bin / activate에 추가 된 행이 DJANGO_SETTINGS_MODULE="SiteName.test_settings"그렇지 않으면 훌륭한 답변입니다!
alexbhandari 2014 년

2
우연의 일치하여 단계로이 단계를하고, 나는 장고에 새로운 오전 방법에 대한 튜토리얼을 알고 어디 DJANGO_SETTINGS_MODULE 또는 PYTHONPATH 설정하는 노하우를하지는 않는다
예수 Almaral - Hackaprende

이 솔루션은 conda 환경에 적용되지 않는 것 같습니다. conda 환경에는 bin / activate가 없습니다.
Pouya Yousefi

1
@PouyaYousefi : 이 답변을 사용하기 위해 virtualenv를 사용할 필요 가 전혀 없습니다 . 대답은 두 단계로 요약됩니다. a) 별도의 설정 파일을 사용하고 b) 사용할 파일 DJANGO_SETTINGS_MODULE을 선택하는 데 사용합니다. 수정 bin/activate 은 후자를 수행하는 것입니다 (TBH, 더 이상 이것이 좋은 생각이라고 생각하지 않아서 제거했습니다).하지만 그게 유일한 것은 아닙니다.
Thomas Orozco

pycharm 커뮤니티 에디션에서 Django를 사용하고 명령 줄과 pycharm 커뮤니티 모두에서 단위 테스트를 올바르게 실행해야하는 경우에도 유용합니다. 소스 저장소의 myapp / settings.py에 간단한 구성 파일을 하나만 만들었다 고 가정합니다. 이 경우 메뉴 RUN / Edit Configuration / Environment 변수에서 "DJANGO_SETTINGS_MODULE = myapp.settings"를 설정하여 후자를 테스트 케이스를 실행하는 데 사용합니다.
F.Tamy 2019-06-03

58

기본적으로 프로덕션 설정을 사용하지만 파일 settings_dev.py과 동일한 폴더에 라는 파일을 만듭니다 settings.py. 여기에 DEBUG=True.

개발에 사용될 컴퓨터에서 다음을 ~/.bashrc파일에 추가 하십시오.

export DJANGO_DEVELOPMENT=true

settings.py파일 하단에 다음을 추가합니다.

# Override production variables if DJANGO_DEVELOPMENT env variable is set
if os.environ.get('DJANGO_DEVELOPMENT'):
    from settings_dev import *  # or specific overrides

( *일반적으로 Python 에서는 가져 오기 를 피해야합니다.)

기본적으로 프로덕션 서버는 아무것도 무시하지 않습니다. 끝난!

다른 답변과 비교할 때 이것은 업데이트가 필요하지 않거나 한 번에 하나의 장고 프로젝트에서만 작업 할 수있는 PYTHONPATH설정 DJANGO_SETTINGS_MODULE이 필요하지 않기 때문에 더 간단 합니다.


8
이것이 정답이 아닌 이유는 무엇입니까? 그래서 요즘은 정말 엉망입니다. Ty cs01
codyc4321

if os.environ.get('DJANGO_DEVELOPMENT', 'true')또한 작동합니다. 위의 is not true방법이 Python 3.6에서 나를 위해 가져 오지 못했기 때문에 이것을 언급 했습니다.
brt

1
@brt 이것은 나쁜 생각입니다 : 항상 여러분의 DEV설정을 사용하여 공용 서버에서 개인 데이터를 유출합니다. DJANGO_DEVELOPMENT환경 변수가 존재 하는지 확인하고 싶을뿐입니다 (예 :) is not None.
cs01

정보 주셔서 감사합니다, @ cs01. 잘못된 설정 로딩으로 내 사이트를 날려 버릴 때 뭔가 잘못되었음을 깨달았지만, 왜 settings_dev.py서버에 로딩 되는지 확신 할 수 없었습니다.
brt

2
@ cs01 나는 is not None수표를 내려 놓음으로써 그것이 존재하고 진실인지 확인하기 위해 갈 것입니다 . 또한 os.getenv약식입니다
Tjorriemorrie

35

일반적으로 환경 당 하나의 설정 파일과 공유 설정 파일이 있습니다.

/myproject/
  settings.production.py
  settings.development.py
  shared_settings.py

각 환경 파일에는 다음이 있습니다.

try:
    from shared_settings import *
except ImportError:
    pass

이를 통해 필요한 경우 공유 설정을 재정의 할 수 있습니다 (해당 스탠자 아래에 수정 사항을 추가하여).

그런 다음 settings.py에 연결하여 사용할 설정 파일을 선택합니다.

ln -s settings.development.py settings.py

2
pep8 금지를 import *어떻게 처리 합니까? 그 수표를 비활성화합니까? 이 가져 오기를에 래핑 exec()했지만이 파일에 정의되지 않은 변수에 대한 조건을 가질 수 없으며 INSTALLED_APPS"정의되지 않음"이기 때문에 변수를 변경할 수 없습니다
Mikhail

11
설정 파일은 Python으로 표현 된 구성만큼 코드가 아니기 때문에 Lint를 사용하지 않습니다.
Daniel Watkins

17

다음은 6 가지 간단한 단계로 수행하는 방법입니다.

  1. 프로젝트 디렉토리 안에 폴더를 만들고 이름을 settings.

    프로젝트 구조 :

    myproject/
           myapp1/
           myapp2/              
           myproject/
                  settings/
  2. 의 내부에 네 개의 파이썬 파일을 작성 settings디렉토리 즉 __init__.py, base.py, dev.pyprod.py

    설정 파일 :

    settings/
         __init__.py
         base.py
         prod.py
         dev.py 
  3. 열고 __init__.py다음 내용으로 채 웁니다.

    init .py :

    from .base import *
    # you need to set "myproject = 'prod'" as an environment variable
    # in your OS (on which your website is hosted)
    if os.environ['myproject'] == 'prod':
       from .prod import *
    else:
       from .dev import *
  4. base.py모든 공통 설정 (프로덕션 및 개발 모두에서 사용됨)을 열고 채 웁니다. 예를 들면 다음과 같습니다.

    base.py :

    import os
    ...
    INSTALLED_APPS = [...]
    MIDDLEWARE = [...]
    TEMPLATES = [{...}]
    ...
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    MEDIA_ROOT = os.path.join(BASE_DIR, '/path/')
    MEDIA_URL = '/path/'
  5. dev.py예를 들어 개발과 관련된 항목을 열고 포함합니다.

    dev.py :

    DEBUG = True
    ALLOWED_HOSTS = ['localhost']
    ...
  6. prod.py예를 들어 프로덕션에 특정한 항목을 열고 포함합니다.

    prod.py :

    DEBUG = False
    ALLOWED_HOSTS = ['www.example.com']
    LOGGING = [...]
    ...

10

settings*.py환경별로 변경해야하는 변수를 추정하여 여러 파일을 만듭니다 . 그런 다음 마스터 settings.py파일 의 끝에서 :

try:
  from settings_dev import *
except ImportError:
  pass

settings_*각 단계에 대해 별도의 파일을 보관합니다 .

settings_dev.py파일 상단에 다음을 추가합니다.

import sys
globals().update(vars(sys.modules['settings']))

수정해야하는 변수를 가져옵니다.

위키 항목 에는 설정을 분할하는 방법에 대한 더 많은 아이디어가 있습니다.


감사합니다 Burham! 앱을 배포 할 때, 배포 설정이 작동하는지 확인하려면 settings_dev 파일을 제거하기 만하면됩니까?
Kristian Roebuck

예, 또는 수입을 다음으로 대체하십시오settings_prod.py
Burhan Khalid

1
배포에서 마스터 settings.py 파일을 편집하면 버전 제어와 충돌하므로 반드시 최선의 방법은 아닙니다. Thomas Orozco의 옵션이 가장 좋습니다. virtualenv postactivate 스크립트 또는 gunicorn 또는 mod_wsgi 설정에서 DJANGO_SETTINGS_MODULE을 설정할 수 있습니다.
Steve Jalim

1
스테이지 별 파일을 소스 제어에 추가하지 않는다는 점을 언급해야 할 것입니다. 나는 프로젝트 단계에 특정한 설정을 밀어 붙이지 않는 것으로 이해했다고 가정했습니다.
Burhan Khalid

virtualenv를 사용하는 경우 일반적으로 기본값은 {{project_name}}. settings입니다. 따라서 '설정'은 sys.modules의 키가 아닙니다. 'myproject.settings'(또는 프로젝트 이름이 무엇이든)입니다. 를 사용 modname = "%s.settings" % ".".join(__name__.split('.')[:-1])하여 전체 모듈 이름을 얻은 다음 globals().update(vars(sys.modules[modname])). 나는 그것이 나를 위해 잘 작동한다는 것을 알았다. 물론 프로그래밍 방식으로 문자열을 선호하는 모듈 이름을 결정하는 것에 대해 잠시 포기하면 대부분의 경우에도 작동 할 것입니다.
에릭

9

나는 멋진 django-configurations 를 사용하고 모든 설정은 내에 저장됩니다 settings.py.

from configurations import Configuration

class Base(Configuration):
    # all the base settings here...
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ...

class Develop(Base):
    # development settings here...
    DEBUG = True 
    ...

class Production(Base):
    # production settings here...
    DEBUG = False

Django 프로젝트를 구성하기 위해 방금 문서를 따랐습니다 .


7

우리가 사용하는 접근 방식은 다음과 같습니다.

  • settings가독성을 위해 설정을 여러 파일로 분할 하는 모듈;
  • .env.jsongit 저장소에서 제외시키려는 자격 증명과 매개 변수를 저장 하는 파일 또는 환경에 따라 다릅니다.
  • env.py파일은 읽기 .env.json파일을

다음 구조를 고려하십시오.

...
.env.json           # the file containing all specific credentials and parameters
.gitignore          # the .gitignore file to exclude `.env.json`
project_name/       # project dir (the one which django-admin.py creates)
  accounts/         # project's apps
    __init__.py
    ...
  ...
  env.py            # the file to load credentials
  settings/
    __init__.py     # main settings file
    database.py     # database conf
    storage.py      # storage conf
    ...
venv                # virtualenv
...

.env.json같은 :

{
    "debug": false,
    "allowed_hosts": ["mydomain.com"],
    "django_secret_key": "my_very_long_secret_key",
    "db_password": "my_db_password",
    "db_name": "my_db_name",
    "db_user": "my_db_user",
    "db_host": "my_db_host",
}

그리고 project_name/env.py:

<!-- language: lang-python -->
import json
import os


def get_credentials():
    env_file_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    with open(os.path.join(env_file_dir, '.env.json'), 'r') as f:
        creds = json.loads(f.read())
    return creds


credentials = get_credentials()

다음 설정을 가질 수 있습니다.

<!-- language: lang-py -->
# project_name/settings/__init__.py
from project_name.env import credentials
from project_name.settings.database import *
from project_name.settings.storage import *
...

SECRET_KEY = credentials.get('django_secret_key')

DEBUG = credentials.get('debug')

ALLOWED_HOSTS = credentials.get('allowed_hosts', [])

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    ...
]

if DEBUG:
    INSTALLED_APPS += ['debug_toolbar']

...

# project_name/settings/database.py
from project_name.env import credentials

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': credentials.get('db_name', ''),
        'USER': credentials.get('db_user', ''),
        'HOST': credentials.get('db_host', ''),
        'PASSWORD': credentials.get('db_password', ''),
        'PORT': '5432',
    }
}

이 솔루션의 이점은 다음과 같습니다.

  • git 저장소를 수정하지 않고 로컬 개발을위한 사용자 특정 자격 증명 및 구성
  • 환경 특정 구성 , 예를 들어 .env.jsondev, stagging 및 production과 같은 세 가지 다른 환경을 가진 세 가지 다른 환경을 가질 수 있습니다 .
  • 자격 증명이 저장소에 없습니다.

이 방법이 도움이되기를 바랍니다.이 솔루션에 대한주의 사항이 있으면 알려주세요.


여기서 가정 env으로 대체하는 것 dev, prod등? 이전 settings.py파일 에는 무엇이 들어 있습니까? 에 무엇이 storage.py있고 database.py?
dbinott

@dbinott 안녕, 당신은 쉽게 업데이트 할 수 있습니다 env.py당신이 선택할 수 있도록 파일로드에 환경 변수로 파일을
Charlesthk

예 : conf = os.environ.get ( 'CONF', '') file_ = f ".env. {conf} .json"
Charlesthk

네이티브 파이썬 데이터 유형과 반대로 json을 사용하는 이유는 무엇입니까?
공습

4

다음 파일 구조를 사용합니다.

project/
   ...
   settings/
   settings/common.py
   settings/local.py
   settings/prod.py
   settings/__init__.py -> local.py

그래서 __init__.py에 (창에서 LN 유닉스 또는 mklink) 링크입니다 local.py으로 할 수 있습니다 또는 prod.py구성이 여전히 있도록 project.settings모듈은 깨끗하고 정리하고, 특정 설정을 사용하려는 경우에는 환경 변수를 사용할 수 있습니다 DJANGO_SETTINGS_MODULEproject.settings.prod당신이 필요로하는 경우 프로덕션 환경에 대한 명령을 실행합니다.

파일 prod.pylocal.py:

from .shared import *

DATABASE = {
    ...
}

그리고 shared.py파일은 특정의 CONFIGS없이 글로벌로 유지합니다.


3

cs01의 답변 구축 :

환경 변수에 문제가있는 경우 해당 값을 문자열로 설정하십시오 (예 : I did DJANGO_DEVELOPMENT="true").

또한 cs01의 파일 워크 플로를 다음과 같이 변경했습니다.

#settings.py
import os
if os.environ.get('DJANGO_DEVELOPMENT') is not None:
    from settings_dev import * 
else:
    from settings_production import *
#settings_dev.py
development settings go here
#settings_production.py
production settings go here

이렇게하면 Django는 적절한 설정 파일을 실행하기 전에 설정 파일 전체를 읽을 필요가 없습니다. 이 솔루션은 프로덕션 파일에 프로덕션 서버에만있는 항목이 필요한 경우 유용합니다.

참고 : 파이썬 3에서, 가져온 파일이있을 필요가 .추가 (예를 들어 from .settings_dev import *)


1

하나의 설정 파일을 유지하고 개발 운영 체제가 프로덕션 운영 체제와 다른 경우 settings.py 하단에 다음을 넣을 수 있습니다.

from sys import platform
if platform == "linux" or platform == "linux2":
    # linux
    # some special setting here for when I'm on my prod server
elif platform == "darwin":
    # OS X
    # some special setting here for when I'm developing on my mac
elif platform == "win32":
    # Windows...
    # some special setting here for when I'm developing on my pc

더 읽기 : Python에서 운영 체제를 어떻게 확인합니까?


1

이것은 대답이 된 것 같지만 버전 관리와 함께 사용하는 방법은 다음과 같습니다.

.gitignore에 추가 한 로컬 개발 환경의 설정과 동일한 디렉토리에 env.py 파일을 설정합니다.

env.py :

#!usr/bin/python

DJANGO_ENV = True
ALLOWED_HOSTS = ['127.0.0.1', 'dev.mywebsite.com']

.gitignore :

mywebsite/env.py

settings.py :

if os.path.exists(os.getcwd() + '/env.py'):
    #env.py is excluded using the .gitignore file - when moving to production we can automatically set debug mode to off:
    from env import *
else:
    DJANGO_ENV = False

DEBUG = DJANGO_ENV

나는 이것이 효과가 있고 훨씬 더 우아하다는 것을 알았습니다. env.py를 사용하면 로컬 환경 변수를 쉽게 볼 수 있으며 여러 settings.py 파일 또는 이와 유사한 파일없이이 모든 것을 처리 할 수 ​​있습니다. 이 방법을 사용하면 프로덕션 서버에서 설정하고 싶지 않은 모든 종류의 로컬 환경 변수를 사용할 수 있습니다. 버전 제어를 통해 .gitignore를 활용하여 모든 것이 원활하게 통합되도록 유지하고 있습니다.


가장 간단한 솔루션. 파일 Config내 클래스의 모든 것을 정의 할 수도 env.py있습니다. 그런 다음 import *에서 모듈을 가져올 수 있습니다 from env import Config. 이렇게 os.path하면이 모든 것을 훨씬 간단하게 만드는 if check 를 사용할 필요가 없습니다 .
Siddharth Pant

0

settings.py생산에 사용 합니다. 동일한 디렉토리 settings_dev.py에서 재정의를 위해 만듭니다 .

# settings_dev.py

from .settings import * 

DEBUG = False

dev 컴퓨터에서 다음을 사용하여 Django 앱을 실행합니다.

DJANGO_SETTINGS_MODULE=<your_app_name>.settings_dev python3 manage.py runserver

찌르기 머신에서 마치 방금 가지고있는 것처럼 실행 settings.py합니다.

장점

  1. settings.py (프로덕션에 사용됨) 다른 환경이 존재한다는 사실에 완전히 무관합니다.
  2. prod와 dev의 차이점을 확인하려면 단일 위치 만 살펴보십시오 settings_dev.py. 구성을 수집 할 필요가 흩어져 없습니다 settings_prod.py, settings_dev.pysettings_shared.py.
  3. 누군가가 프로덕션 문제를 해결 한 후 제품 구성에 설정을 추가하면 (명시 적으로 재정의되지 않는 한) dev 구성에도 표시된다는 것을 안심할 수 있습니다. 따라서 다른 구성 파일 간의 차이가 최소화됩니다.

0

파일 설정 문제로 복사를 선택합니다.

Project
   |---__init__.py   [ write code to copy setting file from subdir to current dir]
   |---settings.py  (do not commit this file to git)
   |---setting1_dir
   |         |--  settings.py
   |---setting2_dir
   |         |--  settings.py

django를 실행하면 __init__py가 실행됩니다. 이때, settings.py in setting1_dir교체 settings.py in Project됩니다.

다른 환경을 선택하는 방법은 무엇입니까?

  • __init__.py직접 수정하십시오 .
  • 수정할 bash 파일을 만듭니다 __init__.py.
  • Linux에서 env를 수정 한 다음 __init__.py이 변수를 읽으십시오.

왜 이런 식으로 사용합니까?

같은 디렉토리에있는 많은 파일이 마음에 들지 않기 때문에 너무 많은 파일이 다른 파트너를 혼란스럽게하고 IDE에 적합하지 않습니다 (IDE는 우리가 사용하는 파일을 찾을 수 없습니다).

이 모든 세부 사항을보고 싶지 않은 경우 프로젝트를 두 부분으로 나눌 수 있습니다.

  1. 프로젝트를 설정하기 위해 Spring Initializr와 같은 작은 도구를 만드십시오. (복사 파일을 좋아하십시오)
  2. 프로젝트 코드

0

Google 클라우드 앱 엔진의 환경 간 구성을 변경하기 위해 다른 app.yaml 파일을 사용하고 있습니다.

이를 사용하여 터미널 명령에서 프록시 연결을 만들 수 있습니다.

./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:1433

https://cloud.google.com/sql/docs/sqlserver/connect-admin-proxy#macos-64-bit

파일 : app.yaml

# [START django_app]
service: development
runtime: python37

env_variables:
  DJANGO_DB_HOST: '/cloudsql/myproject:myregion:myinstance'
  DJANGO_DEBUG: True

handlers:
# This configures Google App Engine to serve the files in the app's static
# directory.
- url: /static
  static_dir: static/

# This handler routes all requests not caught above to your main app. It is
# required when static routes are defined, but can be omitted (along with
# the entire handlers section) when there are no static files defined.
- url: /.*
  script: auto
# [END django_app]

-1

이것은 dev, test 및 prod에 대해 다른 환경을 가진 내 솔루션입니다.

import socket

[...]

DEV_PC = 'PC059'
host_name = socket.gethostname()

if host_name == DEV_PC:
   #do something
   pass
elif [...]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.