gault-millau/project/settings/base.py
2019-10-02 10:16:32 +03:00

457 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Django settings for project project.
Generated by 'django-admin startproject' using Django 2.2.2.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
import sys
from datetime import timedelta
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_ROOT = os.path.abspath(os.path.join(BASE_DIR, '..'))
PUBLIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '..', 'media'))
# # insert apps and libs dirs to sys.path
for path in ('apps', ):
path = os.path.abspath(os.path.join(PROJECT_ROOT, '%s' % path))
path in sys.path or sys.path.insert(0, path)
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'ta$edl0av6n#-xphew5922npa4f*h8mfv#$@4tids*gbrp17&b'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
CONTRIB_APPS = [
'bootstrap_admin',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
]
PROJECT_APPS = [
'advertisement.apps.AdvertisementConfig',
'account.apps.AccountConfig',
'authorization.apps.AuthorizationConfig',
'collection.apps.CollectionConfig',
'establishment.apps.EstablishmentConfig',
'gallery.apps.GalleryConfig',
'location.apps.LocationConfig',
'main.apps.MainConfig',
'news.apps.NewsConfig',
'notification.apps.NotificationConfig',
'partner.apps.PartnerConfig',
'recipe.apps.RecipeConfig',
'search_indexes.apps.SearchIndexesConfig',
'translation.apps.TranslationConfig',
'configuration.apps.ConfigurationConfig',
'timetable.apps.TimetableConfig',
'review.apps.ReviewConfig',
'comment.apps.CommentConfig',
'favorites.apps.FavoritesConfig',
]
EXTERNAL_APPS = [
'corsheaders',
'django_elasticsearch_dsl',
'django_elasticsearch_dsl_drf',
'django_filters',
'drf_yasg',
'fcm_django',
'easy_thumbnails',
'rest_framework',
'rest_framework.authtoken',
'easy_select2',
'oauth2_provider',
'social_django',
'rest_framework_social_oauth2',
'django_extensions',
'rest_framework_simplejwt.token_blacklist',
'solo',
'phonenumber_field',
'storages',
'sorl.thumbnail',
]
INSTALLED_APPS = CONTRIB_APPS + EXTERNAL_APPS + PROJECT_APPS
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'utils.middleware.parse_cookies',
]
ROOT_URLCONF = 'project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'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',
# OAuth
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
],
},
},
]
WSGI_APPLICATION = 'project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USERNAME'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOSTNAME'),
'PORT': os.environ.get('DB_PORT'),
},
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Account settings
AUTH_USER_MODEL = 'account.User'
LOGIN_URL = 'admin:login'
LOGOUT_URL = 'admin:logout'
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'ru-RU'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = (
os.path.abspath(os.path.join(BASE_DIR, 'locale')),
)
AVAILABLE_VERSIONS = {
# 'future': '1.0.1',
'current': '1.0.0',
# 'temp': '1.0.0'
}
# Django Rest Framework
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
'PAGE_SIZE': 10,
'DEFAULT_PAGINATION_CLASS': 'utils.pagination.ProjectMobilePagination',
'COERCE_DECIMAL_TO_STRING': False,
'DEFAULT_AUTHENTICATION_CLASSES': (
# JWT
'utils.authentication.GMJWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
'DEFAULT_VERSION': (AVAILABLE_VERSIONS['current'],),
'ALLOWED_VERSIONS': AVAILABLE_VERSIONS.values(),
'DEFAULT_PERMISSION_CLASSES': (
'utils.permissions.IsAuthenticatedAndTokenIsValid',
),
# 'DATETIME_FORMAT': '%m-%d-%Y %H:%M:%S', # experiment
# 'DATE_FORMAT': '%s.%f', # experiment
}
REST_DATE_FORMAT = '%m-%d-%Y'
REST_DATETIME_FORMAT = '%m-%d-%Y %H:%M:%S'
AUTHENTICATION_BACKENDS = (
# Facebook OAuth2
'social_core.backends.facebook.FacebookAppOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
# django-rest-framework-social-oauth2
'utils.oauth2.GMOAuth2',
# Django
'django.contrib.auth.backends.ModelBackend',
)
# Override default OAuth2 namespace
DRFSO2_URL_NAMESPACE = 'auth'
SOCIAL_AUTH_URL_NAMESPACE = 'auth'
OAUTH2_SOCIAL_AUTH_BACKEND_NAME = 'facebook'
OAUTH2_SOCIAL_AUTH_GRANT_TYPE = 'convert_token'
OAUTH2_PROVIDER_APPLICATION_MODEL = 'authorization.Application'
# Facebook configuration
SOCIAL_AUTH_FACEBOOK_KEY = '386843648701452'
SOCIAL_AUTH_FACEBOOK_SECRET = 'a71cf0bf3980843a8f1ea74c6d805fd7'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', ]
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email',
}
# SMS Settings
SMS_EXPIRATION = 5
SMS_SEND_DELAY = 30
SMS_ATTEMPT_LIMIT = 3
# Following items used in several models
# make auto migrations if change
SMS_CODE_LENGTH = 6
SEND_SMS = True
SMS_CODE_SHOW = False
# SMSC Settings
SMS_SERVICE = 'http://smsc.ru/sys/send.php'
SMS_LOGIN = 'GM2019'
SMS_PASSWORD = '}#6%Qe7CYG7n'
SMS_SENDER = 'GM'
# EMAIL
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'anatolyfeteleu@gmail.com'
EMAIL_HOST_PASSWORD = 'nggrlnbehzksgmbt'
EMAIL_PORT = 587
# Django Rest Swagger
SWAGGER_SETTINGS = {
# "DEFAULT_GENERATOR_CLASS": "rest_framework.schemas.generators.BaseSchemaGenerator",
'JSON_EDITOR': False,
'SHOW_REQUEST_HEADERS': True,
'SECURITY_DEFINITIONS': {
'Basic': {
'type': 'basic'
},
'Token': {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
}
},
}
REDOC_SETTINGS = {
'LAZY_RENDERING': False,
}
# CELERY
BROKER_URL = 'amqp://rabbitmq:5672'
CELERY_RESULT_BACKEND = BROKER_URL
CELERY_BROKER_URL = BROKER_URL
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = TIME_ZONE
# Django FCM (Firebase push notifications)
FCM_DJANGO_SETTINGS = {
'FCM_SERVER_KEY': (
"AAAAJcC4Vbc:APA91bGovq7233-RHu2MbZTsuMU4jNf3obOue8s"
"7qVznx-Xwr_h_R8Nz2Wfhf6hWIXdt99hr6xOH9WRVhxnC5eH96s"
"6rYnpKEY6OrcVoLtceIR1yRrBZJtklDiSkP7daoeCqsnQmtB2m"
),
}
# Thumbnail settings
THUMBNAIL_ALIASES = {
'': {
'news_preview': {'size': (300, 260), },
'news_promo_horizontal_web': {'size': (1900, 600), },
'news_promo_horizontal_mobile': {'size': (375, 260), },
'news_tile_horizontal_web': {'size': (300, 275), },
'news_tile_horizontal_mobile': {'size': (343, 180), },
'news_tile_vertical_web': {'size': (300, 380), },
'news_highlight_vertical_web': {'size': (460, 630), },
'news_editor_web': {'size': (940, 430), }, # при загрузке через контент эдитор
'news_editor_mobile': {'size': (343, 260), }, # через контент эдитор в мобильном браузерe
'avatar_comments_web': {'size': (116, 116), },
}
}
THUMBNAIL_DEFAULT_OPTIONS = {
'crop': 'smart',
}
# SORL
THUMBNAIL_QUALITY = 85
THUMBNAIL_DEBUG = False
SORL_THUMBNAIL_ALIASES = {
'news_preview': {'geometry_string': '100x100', 'crop': 'center'},
'news_promo_horizontal_web': {'geometry_string': '1900x600', 'crop': 'center'},
'news_promo_horizontal_mobile': {'geometry_string': '375x260', 'crop': 'center'},
'news_tile_horizontal_web': {'geometry_string': '300x275', 'crop': 'center'},
'news_tile_horizontal_mobile': {'geometry_string': '343x180', 'crop': 'center'},
'news_tile_vertical_web': {'geometry_string': '300x380', 'crop': 'center'},
'news_highlight_vertical_web': {'geometry_string': '460x630', 'crop': 'center'},
'news_editor_web': {'geometry_string': '940x430', 'crop': 'center'},
'news_editor_mobile': {'geometry_string': '343x260', 'crop': 'center'}, # при загрузке через контент эдитор
'avatar_comments_web': {'geometry_string': '116x116', 'crop': 'center'}, # через контент эдитор в мобильном браузерe
}
# JWT
SIMPLE_JWT = {
# Increase access token lifetime b.c. front-end dev's cant send multiple
# requests to API in one HTTP request.
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
'ACCESS_TOKEN_LIFETIME_SECONDS': 21600, # 6 hours in seconds
'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
'REFRESH_TOKEN_LIFETIME_SECONDS': 2592000, # 30 days in seconds
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken', ),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
# AUTHORIZATION
PASSWORD_RESET_TIMEOUT_DAYS = 1
# TEMPLATES
RESETTING_TOKEN_TEMPLATE = 'account/password_reset_email.html'
CHANGE_EMAIL_TEMPLATE = 'account/change_email.html'
CONFIRM_EMAIL_TEMPLATE = 'authorization/confirm_email.html'
# COOKIES
COOKIES_MAX_AGE = 2628000 # 30 days
SESSION_COOKIE_SAMESITE = None
# CORS
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
# UPLOAD FILES
# Increase upload maximum file size
# Maximum POST data size
DATA_UPLOAD_MAX_MEMORY_SIZE = 5242880 # 5MB
# Maximum uploaded file size
FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880 # 5MB
FILE_UPLOAD_PERMISSIONS = 0o644
# SOLO SETTINGS
# todo: make a separate service (redis?) and update solo_cache
SOLO_CACHE = 'default'
SOLO_CACHE_PREFIX = 'solo'
SOLO_CACHE_TIMEOUT = 300
# REDIRECT URL
SITE_REDIRECT_URL_UNSUBSCRIBE = '/unsubscribe/'
SITE_NAME = 'Gault & Millau'
# Used in annotations for establishments.
DEFAULT_ESTABLISHMENT_PUBLIC_MARK = 10
# Limit output objects (see in pagination classes).
QUERY_OUTPUT_OBJECTS = 12
# Need to restrict objects to sort (3 times more then expected).
LIMITING_QUERY_OBJECTS = QUERY_OUTPUT_OBJECTS * 3
# GEO
# A Spatial Reference System Identifier
GEO_DEFAULT_SRID = 4326
GEOIP_PATH = os.path.join(PROJECT_ROOT, 'geoip_db')
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_ROOT = os.path.join(PUBLIC_ROOT, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(PROJECT_ROOT, 'static'),
)
MEDIA_LOCATION = 'media'