· 4 years ago · Jul 24, 2021, 10:00 AM
1#production.py
2
3import os
4from .common import Common
5import dj_database_url
6
7class Production(Common):
8 INSTALLED_APPS = Common.INSTALLED_APPS
9 SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
10 # Site
11 # https://docs.djangoproject.com/en/2.0/ref/settings/#allowed-hosts
12 ALLOWED_HOSTS = ["*"]
13 INSTALLED_APPS += ("gunicorn", )
14
15 # Static files (CSS, JavaScript, Images)
16 # https://docs.djangoproject.com/en/2.0/howto/static-files/
17 # http://django-storages.readthedocs.org/en/latest/index.html
18 INSTALLED_APPS += ('storages',)
19 DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
20 STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
21 AWS_ACCESS_KEY_ID = os.getenv('DJANGO_AWS_ACCESS_KEY_ID')
22 AWS_SECRET_ACCESS_KEY = os.getenv('DJANGO_AWS_SECRET_ACCESS_KEY')
23 AWS_STORAGE_BUCKET_NAME = os.getenv('DJANGO_AWS_STORAGE_BUCKET_NAME')
24 AWS_DEFAULT_ACL = 'public-read'
25 AWS_AUTO_CREATE_BUCKET = True
26 AWS_QUERYSTRING_AUTH = False
27 POSTGRES_HOST_NAME = os.getenv('POSTGRES_HOST_NAME')
28 POSTGRES_PORT = os.getenv('POSTGRES_PORT', 5432)
29 POSTGRES_DB_NAME = os.getenv('POSTGRES_DB_NAME')
30 POSTGRES_DB_USER = os.getenv('POSTGRES_DB_USER')
31 POSTGRES_USER_PASS = os.getenv('POSTGRES_USER_PASS')
32
33 MEDIA_URL = f'https://s3.amazonaws.com/{AWS_STORAGE_BUCKET_NAME}/'
34
35 # https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#cache-control
36 # Response can be cached by browser and any intermediary caches (i.e. it is "public") for up to 1 day
37 # 86400 = (60 seconds x 60 minutes x 24 hours)
38 AWS_HEADERS = {
39 'Cache-Control': 'max-age=86400, s-maxage=86400, must-revalidate',
40 }
41
42 # Postgres
43 DATABASES = {
44 'default': dj_database_url.config(
45 default=f'postgres://{POSTGRES_DB_USER}:{POSTGRES_USER_PASS}@{POSTGRES_HOST_NAME}:{POSTGRES_PORT}/{POSTGRES_DB_NAME}',
46 conn_max_age=int(os.getenv('POSTGRES_CONN_MAX_AGE', 600))
47 )
48 }
49#local.py
50
51import os
52from .common import Common
53BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
54
55
56class Local(Common):
57 DEBUG = True
58
59 # Testing
60 INSTALLED_APPS = Common.INSTALLED_APPS
61 INSTALLED_APPS += ('django_nose',)
62 TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
63 NOSE_ARGS = [
64 BASE_DIR,
65 '-s',
66 '--nologcapture',
67 '--with-coverage',
68 '--with-progressive',
69 '--cover-package=hakeemdictionarybackend'
70 ]
71
72 # Mail
73 EMAIL_HOST = 'localhost'
74 EMAIL_PORT = 1025
75 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
76
77#common.py
78
79import os
80from os.path import join
81from distutils.util import strtobool
82import dj_database_url
83import datetime
84from configurations import Configuration
85BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
86
87
88class Common(Configuration):
89
90 INSTALLED_APPS = (
91 'django.contrib.admin',
92 'django.contrib.auth',
93 'django.contrib.contenttypes',
94 'django.contrib.sessions',
95 'django.contrib.messages',
96 'django.contrib.staticfiles',
97
98
99 # Third party apps
100 'rest_framework', # utilities for rest apis
101 'rest_framework.authtoken', # token authentication
102 'django_filters', # for filtering rest endpoints
103 'django_q',
104 'corsheaders',
105
106 # Your apps
107 'hakeemdictionarybackend.users',
108 'hakeemdictionarybackend.dictionary',
109
110
111 )
112
113 # https://docs.djangoproject.com/en/2.0/topics/http/middleware/
114 MIDDLEWARE = (
115 'django.middleware.security.SecurityMiddleware',
116 'django.contrib.sessions.middleware.SessionMiddleware',
117 'django.middleware.common.CommonMiddleware',
118 'django.middleware.csrf.CsrfViewMiddleware',
119 'django.contrib.auth.middleware.AuthenticationMiddleware',
120 'django.contrib.messages.middleware.MessageMiddleware',
121 'django.middleware.clickjacking.XFrameOptionsMiddleware',
122 'corsheaders.middleware.CorsMiddleware',
123 )
124
125 ALLOWED_HOSTS = ["*"]
126 ROOT_URLCONF = 'hakeemdictionarybackend.urls'
127 SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
128 WSGI_APPLICATION = 'hakeemdictionarybackend.wsgi.application'
129
130 CORS_ORIGIN_ALLOW_ALL = True
131 # CORS_ALLOW_CREDENTIALS = False
132 # CORS_ORIGIN_WHITELIST = (
133 # # TODO - set this properly for production
134 # 'https://localhost:8000',
135 # 'http://localhost:8000',
136 # )
137
138 # Email
139 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
140
141 ADMINS = (
142 ('Author', 'a.tlimat@gmail.com'),
143 )
144
145 # Postgres
146 DATABASES = {
147 'default': dj_database_url.config(
148 default='postgres://postgres:@postgres:5432/postgres',
149 conn_max_age=int(os.getenv('POSTGRES_CONN_MAX_AGE', 600))
150 )
151 }
152
153 # General
154 APPEND_SLASH = False
155 TIME_ZONE = 'America/New_York'
156 LANGUAGE_CODE = 'en-us'
157 # If you set this to False, Django will make some optimizations so as not
158 # to load the internationalization machinery.
159 USE_I18N = False
160 USE_L10N = True
161 USE_TZ = True
162 LOGIN_REDIRECT_URL = '/'
163
164 # Static files (CSS, JavaScript, Images)
165 # https://docs.djangoproject.com/en/2.0/howto/static-files/
166 STATIC_ROOT = os.path.normpath(join(os.path.dirname(BASE_DIR), 'static'))
167 STATICFILES_DIRS = []
168 STATIC_URL = '/static/'
169 STATICFILES_FINDERS = (
170 'django.contrib.staticfiles.finders.FileSystemFinder',
171 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
172 )
173
174 # Media files
175 MEDIA_ROOT = join(os.path.dirname(BASE_DIR), 'media')
176 MEDIA_URL = '/media/'
177
178 TEMPLATES = [
179 {
180 'BACKEND': 'django.template.backends.django.DjangoTemplates',
181 'DIRS': [BASE_DIR + '/templates'],
182 'APP_DIRS': True,
183 'OPTIONS': {
184 'context_processors': [
185 'django.template.context_processors.debug',
186 'django.template.context_processors.request',
187 'django.contrib.auth.context_processors.auth',
188 'django.contrib.messages.context_processors.messages',
189 ],
190 },
191 },
192 ]
193
194 # Set DEBUG to False as a default for safety
195 # https://docs.djangoproject.com/en/dev/ref/settings/#debug
196 DEBUG = strtobool(os.getenv('DJANGO_DEBUG', 'no'))
197
198 # Password Validation
199 # https://docs.djangoproject.com/en/2.0/topics/auth/passwords/#module-django.contrib.auth.password_validation
200 AUTH_PASSWORD_VALIDATORS = [
201 {
202 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
203 },
204 {
205 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
206 },
207 {
208 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
209 },
210 {
211 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
212 },
213 ]
214
215 Q_CLUSTER = {
216 'redis': {
217 'host': 'redis',
218 'port': 6379,
219 'db': 0,
220 'password': None,
221 'socket_timeout': None,
222 'charset': 'utf-8',
223 'errors': 'strict',
224 'unix_socket_path': None
225 }
226 }
227
228 JWT_AUTH = {
229 'JWT_ALLOW_REFRESH': True,
230 'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
231 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
232 }
233
234 # Logging
235 LOGGING = {
236 'version': 1,
237 'disable_existing_loggers': False,
238 'formatters': {
239 'django.server': {
240 '()': 'django.utils.log.ServerFormatter',
241 'format': '[%(server_time)s] %(message)s',
242 },
243 'verbose': {
244 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
245 },
246 'simple': {
247 'format': '%(levelname)s %(message)s'
248 },
249 },
250 'filters': {
251 'require_debug_true': {
252 '()': 'django.utils.log.RequireDebugTrue',
253 },
254 },
255 'handlers': {
256 'django.server': {
257 'level': 'INFO',
258 'class': 'logging.StreamHandler',
259 'formatter': 'django.server',
260 },
261 'console': {
262 'level': 'DEBUG',
263 'class': 'logging.StreamHandler',
264 'formatter': 'simple'
265 },
266 'mail_admins': {
267 'level': 'ERROR',
268 'class': 'django.utils.log.AdminEmailHandler'
269 }
270 },
271 'loggers': {
272 'django': {
273 'handlers': ['console'],
274 'propagate': True,
275 },
276 'django.server': {
277 'handlers': ['django.server'],
278 'level': 'INFO',
279 'propagate': False,
280 },
281 'django.request': {
282 'handlers': ['mail_admins', 'console'],
283 'level': 'ERROR',
284 'propagate': False,
285 },
286 'django.db.backends': {
287 'handlers': ['console'],
288 'level': 'INFO'
289 },
290 }
291 }
292
293 # Custom user app
294 AUTH_USER_MODEL = 'users.User'
295
296 # Django Rest Framework
297 REST_FRAMEWORK = {
298 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
299 'PAGE_SIZE': int(os.getenv('DJANGO_PAGINATION_LIMIT', 10)),
300 'DATETIME_FORMAT': '%Y-%m-%dT%H:%M:%S%z',
301 'DEFAULT_RENDERER_CLASSES': (
302 'rest_framework.renderers.JSONRenderer',
303 'rest_framework.renderers.BrowsableAPIRenderer',
304 ),
305 'DEFAULT_PERMISSION_CLASSES': [
306 'rest_framework.permissions.IsAuthenticated',
307 ],
308 'DEFAULT_AUTHENTICATION_CLASSES': (
309 'rest_framework.authentication.SessionAuthentication',
310 'rest_framework.authentication.TokenAuthentication',
311 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
312 ),
313 'DEFAULT_THROTTLE_CLASSES': [
314 'rest_framework.throttling.AnonRateThrottle'
315 ],
316 'DEFAULT_THROTTLE_RATES': {'anon': '6/minute'}
317 }
318