> For the complete documentation index, see [llms.txt](https://dahye-jeong.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dahye-jeong.gitbook.io/java/master-1/django/basic/2019-09-24-separatesettings.md).

# Settings 분리하기

## settings.py

`settings.py` 를 왜 분리해야할까?

보통 프로젝트를 시작하면 한개의 `settings.py` 파일이 존재한다. 하지만 실무에서는 로컬환경, 배포환경으로 환경설정이 나누어져있다. 로컬환경은 일반적으로 오류를 검출하기 위한 환경을 가지며, 배포환경에서는 로그 기록이나 오류를 숨겨 사용자 편의성을 도모하고 악의적인 해커로부터 보호하는 환경을 설정한다.

```
config/
├── __init__.py
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── development.py
│   └── production.py
├── urls.py
└── wsgi.py
```

### base.py

`settings/base.py` 에는 1. 각 종 경로 2. 언어, 타임존 등 공통으로 사용되는 설정들이 저장된다.

공통으로 사용되는 각 종 디렉토리 경로, AUTH\_USER\_MODEL, INSTALLED\_APPS 등이 base.py에 설정하게된다.

```python
"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 2.1.7.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os
import sys
import json

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ROOT_DIR = os.path.dirname(BASE_DIR)
SECRETS_PATH = os.path.join(ROOT_DIR, '.config_secret')
SECRET_BASE_FILE = os.path.join(ROOT_DIR, 'base.json')

# json 파일을 python 객체로 변환
base_secrets = json.loads(open(SECRET_BASE_FILE).read())

# json은 dict 자료형으로 변환되므로 .items() 함수를 이용해 key와 value값을 가져온다.
# 이때 settings 모듈에 동적으로 할당한다.
for key, value in base_secrets.items():
    setattr(sys.modules[__name__], key, value)

# Application definition

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

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'config.wsgi.application'

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'ko'

TIME_ZONE = 'Asia/Seoul'

USE_I18N = True

USE_L10N = True

USE_TZ = True
```

### development.py vs Production.

Static 파일의 경로, DB 종류, WSGI 설정, allowed host 등 다양하게 설정을 분리할 수 있다.

`development.py` 와 `p.py` 를 구분짓는 가장 핵심은 Debug 값이다.

```python
Debug = True
```

왜 오류가 났는지 알려주지 않으며 단순히 페이지를 찾을 수 없다는 문구만나온다.

```python
Debug = False
```

오류가 난 이유를 상세하게 알려준다. 어느 파일, 몇번째 줄에서 오류가 발생했는지 알 수 있다.

```
$ ./manage.py runserver --settings=config.settings.development # 개발용
$ ./manage.py runserver --settings=config.settings.production # 배포용
```

#### development.py

```python
from .base import *

SECRETS_DEV_FILE = os.path.join(SECRETS_PATH, 'development.json')

dev_secrets = json.loads(open(SECRETS_DEV_FILE).read())

DEBUG = True

INSTALLED_APPS += [
    'debug_toolbar',
]

MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.path.join(BASE_DIR, 'db.mysql'),
        'USER': dev_secrets['DATABASES']['USER'],
        'PASSWORD': dev_secrets['DATABASES']['PASSWORD']
    }
}
```

### Manage.py

```python
#!/usr/bin/env python
import os
import sys

if __name__ == '__main__':
  # setdefault를 development로 설정해준다.  
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)
```

## wsgi

uswgi명령을 통해서 직접 웹어플리케이션 서버를 실행할 때 사용할 설정 파일을 실행 환경별로 분리할 수 있다.

```
config/
├── __init__.py
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── development.py
│   └── production.py
├── wsgi
│   ├── __init__.py
│   ├── development.py
│   └── production.py
├── urls.py
└── wsgi.py
```

### Development.py

```python
"""
WSGI config for config project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')

application = get_wsgi_application()
```

### production.py

```python
"""
WSGI config for config project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production')

application = get_wsgi_application()
```

## requirements.txt

어떤 패키지는 운영 시에는 사용되지 않지만 개발의 편의를 위해서 필요한 경우가 있다. 이러한 경우에 `requirements.txt` 파일을 분리해서 사용하기도 한다.

```python
├── app
│   ├── config
│   │   ├── __init__.py
│   │   ├── settings
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── development.py
│   │   │   └── production.py
│   │   ├── urls.py
│   │   └── wsgi
│   │       ├── __init__.py
│   │       ├── development.py
│   │       └── production.py
│   └── manage.py
└── requirements
    ├── base.txt
    ├── development.txt
    └── production.txt
```

### base.txt

```
Django==2.1.7
[...]
```

### development.txt

```
-r base.txt
django-debug-toolbar==2.0
[...]
```

## 참고 페이지

* [Django Tips #20 Working With Multiple Settings Modules](https://simpleisbetterthancomplex.com/tips/2017/07/03/django-tip-20-working-with-multiple-settings-modules.html)
* [Django settings.py 환경을 여러개의 설정 파일로 분리하여 사용하기](https://cjh5414.github.io/django-settings-separate/)
* [Django 배포연습 1 - settings, wsgi 분리](https://wayhome25.github.io/django/2018/03/03/django-deploy-01-settings/)
