· 4 years ago · Jul 24, 2021, 09:46 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#production.py
319
320import os
321from .common import Common
322import dj_database_url
323
324class Production(Common):
325 INSTALLED_APPS = Common.INSTALLED_APPS
326 SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
327 # Site
328 # https://docs.djangoproject.com/en/2.0/ref/settings/#allowed-hosts
329 ALLOWED_HOSTS = ["*"]
330 INSTALLED_APPS += ("gunicorn", )
331
332 # Static files (CSS, JavaScript, Images)
333 # https://docs.djangoproject.com/en/2.0/howto/static-files/
334 # http://django-storages.readthedocs.org/en/latest/index.html
335 INSTALLED_APPS += ('storages',)
336 DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
337 STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
338 AWS_ACCESS_KEY_ID = os.getenv('DJANGO_AWS_ACCESS_KEY_ID')
339 AWS_SECRET_ACCESS_KEY = os.getenv('DJANGO_AWS_SECRET_ACCESS_KEY')
340 AWS_STORAGE_BUCKET_NAME = os.getenv('DJANGO_AWS_STORAGE_BUCKET_NAME')
341 AWS_DEFAULT_ACL = 'public-read'
342 AWS_AUTO_CREATE_BUCKET = True
343 AWS_QUERYSTRING_AUTH = False
344 POSTGRES_HOST_NAME = os.getenv('POSTGRES_HOST_NAME')
345 POSTGRES_PORT = os.getenv('POSTGRES_PORT', 5432)
346 POSTGRES_DB_NAME = os.getenv('POSTGRES_DB_NAME')
347 POSTGRES_DB_USER = os.getenv('POSTGRES_DB_USER')
348 POSTGRES_USER_PASS = os.getenv('POSTGRES_USER_PASS')
349
350 MEDIA_URL = f'https://s3.amazonaws.com/{AWS_STORAGE_BUCKET_NAME}/'
351
352 # https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#cache-control
353 # Response can be cached by browser and any intermediary caches (i.e. it is "public") for up to 1 day
354 # 86400 = (60 seconds x 60 minutes x 24 hours)
355 AWS_HEADERS = {
356 'Cache-Control': 'max-age=86400, s-maxage=86400, must-revalidate',
357 }
358
359 # Postgres
360 DATABASES = {
361 'default': dj_database_url.config(
362 default=f'postgres://{POSTGRES_DB_USER}:{POSTGRES_USER_PASS}@{POSTGRES_HOST_NAME}:{POSTGRES_PORT}/{POSTGRES_DB_NAME}',
363 conn_max_age=int(os.getenv('POSTGRES_CONN_MAX_AGE', 600))
364 )
365 }
366#local.py
367
368import os
369from .common import Common
370BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
371
372
373class Local(Common):
374 DEBUG = True
375
376 # Testing
377 INSTALLED_APPS = Common.INSTALLED_APPS
378 INSTALLED_APPS += ('django_nose',)
379 TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
380 NOSE_ARGS = [
381 BASE_DIR,
382 '-s',
383 '--nologcapture',
384 '--with-coverage',
385 '--with-progressive',
386 '--cover-package=hakeemdictionarybackend'
387 ]
388
389 # Mail
390 EMAIL_HOST = 'localhost'
391 EMAIL_PORT = 1025
392 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
393
394#common.py
395
396import os
397from os.path import join
398from distutils.util import strtobool
399import dj_database_url
400import datetime
401from configurations import Configuration
402BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
403
404
405class Common(Configuration):
406
407 INSTALLED_APPS = (
408 'django.contrib.admin',
409 'django.contrib.auth',
410 'django.contrib.contenttypes',
411 'django.contrib.sessions',
412 'django.contrib.messages',
413 'django.contrib.staticfiles',
414
415
416 # Third party apps
417 'rest_framework', # utilities for rest apis
418 'rest_framework.authtoken', # token authentication
419 'django_filters', # for filtering rest endpoints
420 'django_q',
421 'corsheaders',
422
423 # Your apps
424 'hakeemdictionarybackend.users',
425 'hakeemdictionarybackend.dictionary',
426
427
428 )
429
430 # https://docs.djangoproject.com/en/2.0/topics/http/middleware/
431 MIDDLEWARE = (
432 'django.middleware.security.SecurityMiddleware',
433 'django.contrib.sessions.middleware.SessionMiddleware',
434 'django.middleware.common.CommonMiddleware',
435 'django.middleware.csrf.CsrfViewMiddleware',
436 'django.contrib.auth.middleware.AuthenticationMiddleware',
437 'django.contrib.messages.middleware.MessageMiddleware',
438 'django.middleware.clickjacking.XFrameOptionsMiddleware',
439 'corsheaders.middleware.CorsMiddleware',
440 )
441
442 ALLOWED_HOSTS = ["*"]
443 ROOT_URLCONF = 'hakeemdictionarybackend.urls'
444 SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
445 WSGI_APPLICATION = 'hakeemdictionarybackend.wsgi.application'
446
447 CORS_ORIGIN_ALLOW_ALL = True
448 # CORS_ALLOW_CREDENTIALS = False
449 # CORS_ORIGIN_WHITELIST = (
450 # # TODO - set this properly for production
451 # 'https://localhost:8000',
452 # 'http://localhost:8000',
453 # )
454
455 # Email
456 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
457
458 ADMINS = (
459 ('Author', 'a.tlimat@gmail.com'),
460 )
461
462 # Postgres
463 DATABASES = {
464 'default': dj_database_url.config(
465 default='postgres://postgres:@postgres:5432/postgres',
466 conn_max_age=int(os.getenv('POSTGRES_CONN_MAX_AGE', 600))
467 )
468 }
469
470 # General
471 APPEND_SLASH = False
472 TIME_ZONE = 'America/New_York'
473 LANGUAGE_CODE = 'en-us'
474 # If you set this to False, Django will make some optimizations so as not
475 # to load the internationalization machinery.
476 USE_I18N = False
477 USE_L10N = True
478 USE_TZ = True
479 LOGIN_REDIRECT_URL = '/'
480
481 # Static files (CSS, JavaScript, Images)
482 # https://docs.djangoproject.com/en/2.0/howto/static-files/
483 STATIC_ROOT = os.path.normpath(join(os.path.dirname(BASE_DIR), 'static'))
484 STATICFILES_DIRS = []
485 STATIC_URL = '/static/'
486 STATICFILES_FINDERS = (
487 'django.contrib.staticfiles.finders.FileSystemFinder',
488 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
489 )
490
491 # Media files
492 MEDIA_ROOT = join(os.path.dirname(BASE_DIR), 'media')
493 MEDIA_URL = '/media/'
494
495 TEMPLATES = [
496 {
497 'BACKEND': 'django.template.backends.django.DjangoTemplates',
498 'DIRS': [BASE_DIR + '/templates'],
499 'APP_DIRS': True,
500 'OPTIONS': {
501 'context_processors': [
502 'django.template.context_processors.debug',
503 'django.template.context_processors.request',
504 'django.contrib.auth.context_processors.auth',
505 'django.contrib.messages.context_processors.messages',
506 ],
507 },
508 },
509 ]
510
511 # Set DEBUG to False as a default for safety
512 # https://docs.djangoproject.com/en/dev/ref/settings/#debug
513 DEBUG = strtobool(os.getenv('DJANGO_DEBUG', 'no'))
514
515 # Password Validation
516 # https://docs.djangoproject.com/en/2.0/topics/auth/passwords/#module-django.contrib.auth.password_validation
517 AUTH_PASSWORD_VALIDATORS = [
518 {
519 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
520 },
521 {
522 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
523 },
524 {
525 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
526 },
527 {
528 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
529 },
530 ]
531
532 Q_CLUSTER = {
533 'redis': {
534 'host': 'redis',
535 'port': 6379,
536 'db': 0,
537 'password': None,
538 'socket_timeout': None,
539 'charset': 'utf-8',
540 'errors': 'strict',
541 'unix_socket_path': None
542 }
543 }
544
545 JWT_AUTH = {
546 'JWT_ALLOW_REFRESH': True,
547 'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
548 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
549 }
550
551 # Logging
552 LOGGING = {
553 'version': 1,
554 'disable_existing_loggers': False,
555 'formatters': {
556 'django.server': {
557 '()': 'django.utils.log.ServerFormatter',
558 'format': '[%(server_time)s] %(message)s',
559 },
560 'verbose': {
561 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
562 },
563 'simple': {
564 'format': '%(levelname)s %(message)s'
565 },
566 },
567 'filters': {
568 'require_debug_true': {
569 '()': 'django.utils.log.RequireDebugTrue',
570 },
571 },
572 'handlers': {
573 'django.server': {
574 'level': 'INFO',
575 'class': 'logging.StreamHandler',
576 'formatter': 'django.server',
577 },
578 'console': {
579 'level': 'DEBUG',
580 'class': 'logging.StreamHandler',
581 'formatter': 'simple'
582 },
583 'mail_admins': {
584 'level': 'ERROR',
585 'class': 'django.utils.log.AdminEmailHandler'
586 }
587 },
588 'loggers': {
589 'django': {
590 'handlers': ['console'],
591 'propagate': True,
592 },
593 'django.server': {
594 'handlers': ['django.server'],
595 'level': 'INFO',
596 'propagate': False,
597 },
598 'django.request': {
599 'handlers': ['mail_admins', 'console'],
600 'level': 'ERROR',
601 'propagate': False,
602 },
603 'django.db.backends': {
604 'handlers': ['console'],
605 'level': 'INFO'
606 },
607 }
608 }
609
610 # Custom user app
611 AUTH_USER_MODEL = 'users.User'
612
613 # Django Rest Framework
614 REST_FRAMEWORK = {
615 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
616 'PAGE_SIZE': int(os.getenv('DJANGO_PAGINATION_LIMIT', 10)),
617 'DATETIME_FORMAT': '%Y-%m-%dT%H:%M:%S%z',
618 'DEFAULT_RENDERER_CLASSES': (
619 'rest_framework.renderers.JSONRenderer',
620 'rest_framework.renderers.BrowsableAPIRenderer',
621 ),
622 'DEFAULT_PERMISSION_CLASSES': [
623 'rest_framework.permissions.IsAuthenticated',
624 ],
625 'DEFAULT_AUTHENTICATION_CLASSES': (
626 'rest_framework.authentication.SessionAuthentication',
627 'rest_framework.authentication.TokenAuthentication',
628 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
629 ),
630 'DEFAULT_THROTTLE_CLASSES': [
631 'rest_framework.throttling.AnonRateThrottle'
632 ],
633 'DEFAULT_THROTTLE_RATES': {'anon': '6/minute'}
634 }
635