Coverage for src/settings.py: 100%

77 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-09-21 16:24 +0300

1import os 

2from pathlib import Path 

3from datetime import timedelta 

4 

5from django.utils.translation import gettext_lazy as _ 

6from decouple import config 

7 

8import cloudinary 

9import cloudinary.uploader 

10import cloudinary.api 

11 

12import sentry_sdk 

13 

14from .unfold import UNFOLD 

15 

16BASE_DIR = Path(__file__).resolve().parent.parent 

17 

18SECRET_KEY = os.getenv('SECRET_KEY', config('SECRET_KEY')) 

19 

20DEBUG = os.getenv('DEBUG', config('DEBUG')) == 'True' 

21 

22ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', config('ALLOWED_HOSTS')).split(',') 

23 

24CSRF_TRUSTED_ORIGINS = os.getenv( 

25 'CSRF_TRUSTED_ORIGINS', config('CSRF_TRUSTED_ORIGINS', []) 

26).split(',') 

27 

28CORS_ALLOWED_ORIGINS = os.getenv( 

29 'CORS_ALLOWED_ORIGINS', config('CORS_ALLOWED_ORIGINS') 

30).split(',') 

31 

32OPENAI_API_KEY = os.getenv( 

33 'OPENAI_API_KEY', config('OPENAI_API_KEY') 

34) 

35PINECONE_API_KEY = os.getenv( 

36 'PINECONE_API_KEY', config('PINECONE_API_KEY') 

37) 

38PINECONE_INDEX_NAME = os.getenv( 

39 'PINECONE_INDEX_NAME', config('PINECONE_INDEX_NAME') 

40) 

41LANGSMITH_API_KEY = os.getenv( 

42 'LANGSMITH_API_KEY', config('LANGSMITH_API_KEY') 

43) 

44LANGSMITH_TRACING = "true" 

45LANGSMITH_ENDPOINT = "https://api.smith.langchain.com" 

46LANGSMITH_PROJECT = "pr-impassioned-warfare-85" 

47 

48os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY 

49os.environ['LANGSMITH_API_KEY'] = LANGSMITH_API_KEY 

50os.environ['LANGSMITH_ENDPOINT'] = LANGSMITH_ENDPOINT 

51os.environ['PINECONE_API_KEY'] = PINECONE_API_KEY 

52os.environ['PINECONE_INDEX_NAME'] = PINECONE_INDEX_NAME 

53os.environ['LANGSMITH_TRACING_V2'] = 'true' 

54 

55# Custom Django applications in this project 

56PROJECT_APPS = [ 

57 'src.accounts', 

58 'src.chatbot', 

59 'src.common', 

60 'src.products', 

61 'src.shopping_bags', 

62 'src.wishlists', 

63 'src.orders', 

64] 

65 

66INSTALLED_APPS = [ 

67 'unfold', 

68 'unfold.contrib.filters', 

69 'unfold.contrib.forms', 

70 'cloudinary', 

71 'cloudinary_storage', 

72 'django_celery_beat', 

73 'daphne', 

74 'django.contrib.admin', 

75 'django.contrib.auth', 

76 'django.contrib.contenttypes', 

77 'django.contrib.sessions', 

78 'django.contrib.messages', 

79 'django.contrib.staticfiles', 

80 'rest_framework', 

81 'rest_framework_simplejwt', 

82 'rest_framework_simplejwt.token_blacklist', 

83 'corsheaders', 

84 'drf_spectacular', 

85] + PROJECT_APPS 

86 

87ASGI_APPLICATION = 'src.asgi.application' 

88 

89REST_FRAMEWORK = { 

90 'DEFAULT_AUTHENTICATION_CLASSES': [ 

91 'rest_framework_simplejwt.authentication.JWTAuthentication', 

92 ], 

93 'DEFAULT_PERMISSION_CLASSES': [ 

94 'rest_framework.permissions.IsAuthenticated', 

95 ], 

96 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 

97 

98} 

99 

100SIMPLE_JWT = { 

101 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15), 

102 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), 

103} 

104 

105SPECTACULAR_SETTINGS = { 

106 'TITLE': 'DRF React Gems', 

107 'DESCRIPTION': 'E-commerce platform', 

108 'VERSION': '1.0.0', 

109} 

110 

111MIDDLEWARE = [ 

112 'corsheaders.middleware.CorsMiddleware', 

113 'django.middleware.security.SecurityMiddleware', 

114 'whitenoise.middleware.WhiteNoiseMiddleware', 

115 'django.contrib.sessions.middleware.SessionMiddleware', 

116 'django.middleware.common.CommonMiddleware', 

117 'django.middleware.csrf.CsrfViewMiddleware', 

118 'django.contrib.auth.middleware.AuthenticationMiddleware', 

119 'django.contrib.messages.middleware.MessageMiddleware', 

120 'django.middleware.clickjacking.XFrameOptionsMiddleware', 

121] 

122 

123ROOT_URLCONF = 'src.urls' 

124 

125TEMPLATES = [ 

126 { 

127 'BACKEND': 'django.template.backends.django.DjangoTemplates', 

128 'DIRS': [BASE_DIR / 'templates'], 

129 'APP_DIRS': True, 

130 'OPTIONS': { 

131 'context_processors': [ 

132 'django.template.context_processors.request', 

133 'django.contrib.auth.context_processors.auth', 

134 'django.contrib.messages.context_processors.messages', 

135 ], 

136 }, 

137 }, 

138] 

139 

140WSGI_APPLICATION = 'src.wsgi.application' 

141 

142AUTHENTICATION_BACKENDS = [ 

143 # Custom authentication backend 

144 'src.accounts.authentication.CustomAuthBackendBackend', 

145 'django.contrib.auth.backends.ModelBackend', 

146] 

147 

148DATABASES = { 

149 'default': { 

150 'ENGINE': 'django.db.backends.postgresql', 

151 'NAME': os.getenv('DB_NAME', config('DB_NAME')), 

152 'USER': os.getenv('DB_USER', config('DB_USER')), 

153 'PASSWORD': os.getenv('DB_PASS', config('DB_PASS')), 

154 'HOST': os.getenv('DB_HOST', config('DB_HOST')), 

155 'PORT': os.getenv('DB_PORT', config('DB_PORT')), 

156 } 

157} 

158 

159AUTH_PASSWORD_VALIDATORS = [ 

160 { 

161 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 

162 }, 

163 { 

164 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 

165 'OPTIONS': {'min_length': 6}, 

166 }, 

167 { 

168 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 

169 }, 

170 { 

171 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 

172 }, 

173 # Custom validators 

174 { 

175 'NAME': 'src.accounts.validators.password.DigitRequiredValidator', 

176 }, 

177 { 

178 'NAME': 'src.accounts.validators.password.UpperCaseLetterRequiredValidator', 

179 }, 

180 { 

181 'NAME': 'src.accounts.validators.password.LowerCaseLetterRequiredValidator', 

182 }, 

183 { 

184 'NAME': 'src.accounts.validators.password.NoWhiteSpacesRequiredValidator', 

185 }, 

186 { 

187 'NAME': 'src.accounts.validators.password.SpecialCharRequiredValidator', 

188 }, 

189] 

190 

191AUTH_USER_MODEL = 'accounts.UserCredential' 

192 

193PASSWORD_RESET_TIMEOUT = 3600 

194 

195LANGUAGE_CODE = 'en-us' 

196TIME_ZONE = 'UTC' 

197USE_I18N = True 

198USE_TZ = True 

199 

200STATIC_URL = 'static/' 

201STATIC_ROOT = BASE_DIR / 'staticfiles' 

202 

203STATICFILES_DIRS = [ 

204 BASE_DIR / 'static', 

205] 

206 

207STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' 

208 

209STORAGES = { 

210 "default": { 

211 "BACKEND": "cloudinary_storage.storage.MediaCloudinaryStorage", 

212 }, 

213 "staticfiles": { 

214 "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", 

215 }, 

216} 

217 

218MEDIA_URL = 'media/' 

219MEDIA_ROOT = BASE_DIR / 'mediafiles/' 

220 

221DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 

222 

223cloudinary.config( 

224 cloud_name=os.getenv('CLOUD_NAME', config('CLOUD_NAME')), 

225 api_key=os.getenv('CLOUD_API_KEY', config('CLOUD_API_KEY')), 

226 api_secret=os.getenv('CLOUD_API_SECRET', config('CLOUD_API_SECRET')), 

227) 

228 

229CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', config('CELERY_BROKER_URL')) 

230CELERY_RESULT_BACKEND = os.getenv( 

231 'CELERY_RESULT_BACKEND', config('CELERY_RESULT_BACKEND') 

232) 

233CELERY_ACCEPT_CONTENT = ['application/json'] 

234CELERY_TASK_SERIALIZER = 'json' 

235CELERY_RESULT_SERIALIZER = 'json' 

236CELERY_TIMEZONE = TIME_ZONE 

237CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler' 

238CELERY_BROKER_POOL_LIMIT = 2 

239CELERY_RESULT_BACKEND_CONNECTION_RETRY_ON_STARTUP = True 

240 

241EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' 

242EMAIL_USE_TLS = True 

243EMAIL_USE_SSL = False 

244EMAIL_HOST = os.getenv('EMAIL_HOST', config('EMAIL_HOST')) 

245EMAIL_PORT = os.getenv('EMAIL_PORT', config('EMAIL_PORT')) 

246EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER', config('EMAIL_HOST_USER')) 

247DEFAULT_FROM_EMAIL = os.getenv( 

248 'DEFAULT_FROM_EMAIL', config('DEFAULT_FROM_EMAIL') 

249) 

250SERVER_EMAIL = os.getenv('SERVER_EMAIL', config('SERVER_EMAIL')) 

251EMAIL_HOST_PASSWORD = os.getenv( 

252 'EMAIL_HOST_PASSWORD', config('EMAIL_HOST_PASSWORD') 

253) 

254 

255sentry_sdk.init( 

256 dsn=os.getenv('SENTRY_DSN', config('SENTRY_DSN')), 

257 send_default_pii=True, 

258) 

259 

260FRONTEND_URL = os.getenv('FRONTEND_URL', config('FRONTEND_URL'))