Skip to content

Commit 794d6d3

Browse files
committed
deploye final solve blog
1 parent b72997e commit 794d6d3

File tree

2 files changed

+118
-61
lines changed

2 files changed

+118
-61
lines changed

config/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import pymysql
2+
3+
# Configure PyMySQL to work with Django's MySQL backend
4+
pymysql.install_as_MySQLdb()

config/settings.py

Lines changed: 114 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os, sys
1+
import os
22
from pathlib import Path
33
from dotenv import load_dotenv
44

@@ -7,17 +7,31 @@
77

88
BASE_DIR = Path(__file__).resolve().parent.parent
99

10-
SECRET_KEY = os.getenv('SECRET_KEY', "django-insecure-6d0sc!g!$b+ecm0!uttm8)zco12u72)*gmtc61j3n_t0(lgf7v")
11-
DEBUG = os.getenv('DEBUG', 'True').lower() == 'true'
12-
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '').split(',') if os.getenv('ALLOWED_HOSTS') else []
10+
# SECURITY WARNING: keep the secret key used in production secret!
11+
SECRET_KEY = os.getenv('SECRET_KEY', 'generate-a-new-secret-key-for-production')
1312

14-
# Gemini AI Configuration
15-
GEMINI_API_KEY = os.getenv('GEMINI_API_KEY')
13+
# SECURITY WARNING: don't run with debug turned on in production!
14+
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
15+
16+
# Production ALLOWED_HOSTS for cPanel
17+
ALLOWED_HOSTS = [
18+
'roshandamor.me',
19+
'www.roshandamor.me',
20+
'127.0.0.1',
21+
'localhost',
22+
]
1623

17-
# Spotify Configuration
24+
# Add environment variable support for dynamic hosts
25+
env_hosts = os.getenv('ALLOWED_HOSTS', '')
26+
if env_hosts:
27+
ALLOWED_HOSTS.extend([host.strip() for host in env_hosts.split(',') if host.strip()])
28+
29+
# API Keys and External Services
30+
GEMINI_API_KEY = os.getenv('GEMINI_API_KEY')
1831
SPOTIFY_CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID')
1932
SPOTIFY_CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET')
20-
SPOTIFY_REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI', 'http://localhost:8000/music/admin/spotify-callback/')
33+
SPOTIFY_REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI', 'https://roshandamor.me/music/admin/spotify-callback/')
34+
TINYMCE_API_KEY = os.getenv('TINYMCE_API_KEY', '')
2135

2236
INSTALLED_APPS = [
2337
'django.contrib.admin',
@@ -37,8 +51,9 @@
3751

3852
MIDDLEWARE = [
3953
'django.middleware.security.SecurityMiddleware',
40-
"whitenoise.middleware.WhiteNoiseMiddleware",
54+
'whitenoise.middleware.WhiteNoiseMiddleware',
4155
'django.contrib.sessions.middleware.SessionMiddleware',
56+
'corsheaders.middleware.CorsMiddleware',
4257
'django.middleware.common.CommonMiddleware',
4358
'django.middleware.csrf.CsrfViewMiddleware',
4459
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -55,6 +70,7 @@
5570
'APP_DIRS': True,
5671
'OPTIONS': {
5772
'context_processors': [
73+
'django.template.context_processors.debug',
5874
'django.template.context_processors.request',
5975
'django.contrib.auth.context_processors.auth',
6076
'django.contrib.messages.context_processors.messages',
@@ -66,16 +82,31 @@
6682

6783
WSGI_APPLICATION = 'config.wsgi.application'
6884

69-
70-
# Database
71-
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
72-
73-
DATABASES = {
74-
'default': {
75-
'ENGINE': 'django.db.backends.sqlite3',
76-
'NAME': BASE_DIR / 'db.sqlite3',
85+
# Database Configuration for cPanel MySQL
86+
if DEBUG:
87+
# Local development with SQLite
88+
DATABASES = {
89+
'default': {
90+
'ENGINE': 'django.db.backends.sqlite3',
91+
'NAME': BASE_DIR / 'db.sqlite3',
92+
}
93+
}
94+
else:
95+
# Production cPanel MySQL
96+
DATABASES = {
97+
'default': {
98+
'ENGINE': 'django.db.backends.mysql',
99+
'NAME': os.getenv('MYSQL_DB', 'portfolio_db'),
100+
'USER': os.getenv('MYSQL_USER', 'portfolio_user'),
101+
'PASSWORD': os.getenv('MYSQL_PASSWORD', ''),
102+
'HOST': os.getenv('MYSQL_HOST', 'localhost'),
103+
'PORT': os.getenv('MYSQL_PORT', '3306'),
104+
'OPTIONS': {
105+
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
106+
'charset': 'utf8mb4',
107+
},
108+
}
77109
}
78-
}
79110

80111

81112
# Password validation
@@ -106,32 +137,22 @@
106137
USE_TZ = True
107138

108139

109-
# Static files (CSS, JavaScript, Images)
110-
# https://docs.djangoproject.com/en/5.2/howto/static-files/
111-
140+
# Static files configuration for cPanel
112141
STATIC_URL = '/static/'
113142
STATICFILES_DIRS = [BASE_DIR / 'static']
114143
STATIC_ROOT = BASE_DIR / 'staticfiles'
115144

145+
# WhiteNoise configuration for serving static files
146+
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
147+
148+
# Media files configuration
116149
MEDIA_URL = '/media/'
117150
MEDIA_ROOT = BASE_DIR / 'media'
118151

119152
# Default primary key field type
120-
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
121-
122153
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
123154

124-
# TinyMCE settings
125-
TINYMCE_DEFAULT_CONFIG = {
126-
"height": "420px",
127-
"width": "100%",
128-
"menubar": "file edit view insert format tools table help",
129-
"plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code fullscreen insertdatetime media table paste code help wordcount",
130-
"toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media pageembed template link anchor codesample | a11ycheck ltr rtl | showcomments addcomment",
131-
"custom_undo_redo_levels": 10,
132-
}
133-
134-
# TinyMCE Configuration (for rich text editing in Django admin)
155+
# TinyMCE Configuration
135156
TINYMCE_DEFAULT_CONFIG = {
136157
'height': 300,
137158
'width': '100%',
@@ -160,26 +181,25 @@
160181
'statusbar': True,
161182
}
162183

163-
# Email settings
164-
# For development - prints emails to console
165-
# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
166-
167-
# For production - use SMTP (uncomment and configure the lines below)
168-
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
169-
EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.gmail.com') # e.g., smtp.gmail.com for Gmail
170-
EMAIL_PORT = int(os.getenv('EMAIL_PORT', '587'))
171-
EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS', 'True').lower() == 'true'
172-
EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL', 'False').lower() == 'true'
173-
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER', '') # Your email address
174-
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD', '') # Your email password or app password
175-
176-
# Default sender email
177-
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'noreply@yourportfolio.com')
178-
SERVER_EMAIL = DEFAULT_FROM_EMAIL
179-
180-
# Site configuration for emails
184+
# Email Configuration
185+
if DEBUG:
186+
# Development: Console backend
187+
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
188+
else:
189+
# Production: SMTP backend for cPanel
190+
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
191+
EMAIL_HOST = os.getenv('EMAIL_HOST', 'mail.roshandamor.me')
192+
EMAIL_PORT = int(os.getenv('EMAIL_PORT', '465'))
193+
EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS', 'False').lower() == 'true'
194+
EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL', 'True').lower() == 'true'
195+
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER', 'noreply@roshandamor.me')
196+
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD', '')
197+
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'noreply@roshandamor.me')
198+
SERVER_EMAIL = DEFAULT_FROM_EMAIL
199+
200+
# Site Configuration
181201
SITE_NAME = os.getenv('SITE_NAME', 'Roshan Damor Portfolio')
182-
SITE_URL = os.getenv('SITE_URL', 'http://localhost:8000')
202+
SITE_URL = os.getenv('SITE_URL', 'https://roshandamor.me' if not DEBUG else 'http://localhost:8000')
183203

184204
# Message tags for Bootstrap
185205
from django.contrib.messages import constants as messages
@@ -191,15 +211,43 @@
191211
messages.ERROR: 'danger',
192212
}
193213

194-
SPOTIFY_CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID', "your_client_id")
195-
SPOTIFY_CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET', "your_client_secret")
196-
SPOTIFY_REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI', "https://localhost:8000/callback/")
214+
# External API Configuration
215+
SPOTIFY_CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID', '')
216+
SPOTIFY_CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET', '')
217+
SPOTIFY_REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI', 'https://roshandamor.me/music/admin/spotify-callback/')
218+
219+
# Security Settings for Production
220+
if not DEBUG:
221+
# HTTPS and Security
222+
SECURE_BROWSER_XSS_FILTER = True
223+
SECURE_CONTENT_TYPE_NOSNIFF = True
224+
X_FRAME_OPTIONS = 'DENY'
225+
SECURE_HSTS_SECONDS = 31536000 # 1 year
226+
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
227+
SECURE_HSTS_PRELOAD = True
228+
229+
# Session Security
230+
SESSION_COOKIE_SECURE = True
231+
CSRF_COOKIE_SECURE = True
232+
SESSION_COOKIE_HTTPONLY = True
233+
CSRF_COOKIE_HTTPONLY = True
234+
235+
# Force HTTPS redirects (optional for cPanel)
236+
# SECURE_SSL_REDIRECT = True
237+
238+
# CORS Configuration
239+
CORS_ALLOWED_ORIGINS = [
240+
"https://roshandamor.me",
241+
"https://www.roshandamor.me",
242+
]
197243

198-
# Notification System Settings
199-
SITE_NAME = "Roshan Damor Portfolio"
200-
SITE_URL = os.getenv('SITE_URL', 'http://localhost:8000')
244+
if DEBUG:
245+
CORS_ALLOWED_ORIGINS.extend([
246+
"http://localhost:8000",
247+
"http://127.0.0.1:8000",
248+
])
201249

202-
# Logging Configuration for Notifications
250+
# Logging Configuration
203251
LOGGING = {
204252
'version': 1,
205253
'disable_existing_loggers': False,
@@ -221,7 +269,7 @@
221269
'formatter': 'verbose',
222270
},
223271
'console': {
224-
'level': 'DEBUG',
272+
'level': 'DEBUG' if DEBUG else 'INFO',
225273
'class': 'logging.StreamHandler',
226274
'formatter': 'simple',
227275
},
@@ -232,5 +280,10 @@
232280
'level': 'INFO',
233281
'propagate': True,
234282
},
283+
'django': {
284+
'handlers': ['console'],
285+
'level': 'INFO' if DEBUG else 'WARNING',
286+
'propagate': False,
287+
},
235288
},
236289
}

0 commit comments

Comments
 (0)