Django 中统一配置的做法

本文主要描述如何在 django 中统一 settings 文件

背景

django 服务会有多个环境,比如 开发环境、测试环境以及线上环境等。现在大部分使用的方案是针对每一种环境使用一个 settings 文件,然后在不同的环境中使用不同的 settings 文件。这样的设计我认为有至少两个问题:

  1. 很多公用的配置不太好公用
  2. 文件数会很多,项目中管理会比较麻烦

新方案

针对 settings 文件,在 django 项目中可以使用 django-configuration module 进行管理,从而解决上面的两个问题。

实现

  1. 使用 pip install django-configurations 安装 django-configuration module
  2. 修改 settings.py manager.py 以及 wsgi.py 三个文件即可
  3. 建立一个配置统一的文件,用于管理不同的配置项

具体 Demo

settings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from configurations import Configuration
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
class Common(Configuration):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'secret_key'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 'leopard.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 = 'leopard.wsgi.application'
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
STATE_REDIS_DB = 6
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(funcName)s %(message)s'
},
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler'
},
'realtimejob_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'filename',
'formatter': 'verbose'
},
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'django_crontab.crontab': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
'realtimejob': {
'handlers': ['realtimejob_file'],
'level': 'INFO',
'propagate': False
},
},
}
class Dev(Common):
DEBUG = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'name',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'host',
'PORT': 'port',
}
}
STATE_REDIS_HOST = '127.0.0.1'
STATE_REDIS_PORT = 6379
STATE_REDIS_SOCKET_TIMEOUT = 1000
class Prod(Common):
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'name',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'host',
'PORT': 'port',
}
}

manager.py

1
2
3
4
5
6
7
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev') #设置默认的环境
from configurations.management import execute_from_command_line # 引入需要的包
execute_from_command_line(sys.argv) # 使用 django-configurations 来启动

wsgi.py 修改同上所示

1
2
3
4
5
6
7
import os
from configurations.wsgi import get_wsgi_application # 引入相关的包
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
application = get_wsgi_application() # 使用 django-configurations 中的如括进行启动

对于希望针对不同的环境引入不同的变量值(变量名字一样),可以新建一个 commonsettings.py 文件。demo 如下

1
2
3
4
5
6
7
8
import settings
import os
DJANGO_CONFIGURATION_KEY = 'DJANGO_CONFIGURATION'
STATE_REDIS_HOST = getattr(settings, os.environ.get(DJANGO_CONFIGURATION_KEY, 'Dev')).STATE_REDIS_HOST
STATE_REDIS_PORT = getattr(settings, os.environ.get(DJANGO_CONFIGURATION_KEY, 'Dev')).STATE_REDIS_PORT
STATE_REDIS_DB = getattr(settings, os.environ.get(DJANGO_CONFIGURATION_KEY, 'Dev')).STATE_REDIS_DB
STATE_REDIS_SOCKET_TIMEOUT = getattr(settings, os.environ.get(DJANGO_CONFIGURATION_KEY, 'Dev')).STATE_REDIS_SOCKET_TIMEOUT

这样,所有的人从 commonsettings.py 进行引入即可,不需要关心使用的那个环境(commonsettings.py 中没有处理异常,希望对于异常情况提前抛出来)

Comments