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


129

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

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

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

답변:


109

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

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

방법은 다음과 같습니다.

Django 문서에서 언급했듯이 :

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

자, 사용자가 만든 가정하자 myapp/production_settings.py및 myapp/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.py및prod.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_MODULE에 project.settings.prod당신이 필요로하는 경우 프로덕션 환경에 대한 명령을 실행합니다.

파일 prod.py및 local.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.py및 settings_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.