1
0
Fork 0
mirror of https://github.com/EDeev/deev.space.git synced 2026-10-07 20:49:59 +03:00
deev.space/dspace/settings.py
Egor Deev 878b4580e4 Версия 2.0: код с продакшена deev.space
Перенесено всё, что накопилось на сервере с декабря 2025:
- анонимный посетитель по подписанной cookie (main/middleware.py), лайки и дизлайки
  без регистрации с антинакруткой, уникальные просмотры статей;
- карточка-паспорт, стек в одну строку, блок «В цифрах»;
- миграции 0005–0008, команды load_initial_data и populate_demo, robots.txt;
- обновлённые шаблоны, стили и скрипты.

Безопасность и порядок:
- все секреты только из окружения, значения по умолчанию пустые;
- DEBUG по умолчанию выключен, без DJANGO_SECRET_KEY запуск в бою невозможен;
- ALLOWED_HOSTS, путь к базе и SSL-редирект настраиваются переменными;
- убрана статика админки Django (результат collectstatic) и media из git;
- добавлены .gitignore и .gitattributes (переводы строк — LF).
2026-10-02 11:58:54 +00:00

190 lines
No EOL
5.8 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.

import os
from pathlib import Path
from django.core.exceptions import ImproperlyConfigured
from dotenv import load_dotenv
load_dotenv()
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-dev-only-change-me')
DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'True'
if not DEBUG and SECRET_KEY.startswith('django-insecure'):
raise ImproperlyConfigured('Задайте DJANGO_SECRET_KEY для запуска с DJANGO_DEBUG=False')
ALLOWED_HOSTS = os.environ.get(
'DJANGO_ALLOWED_HOSTS',
'deev.space,www.deev.space,deev.su,www.deev.su,xdeev.ru,www.xdeev.ru,localhost,127.0.0.1',
).split(',')
CSRF_TRUSTED_ORIGINS = [o for o in os.environ.get('DJANGO_CSRF_TRUSTED_ORIGINS', '').split(',') if o]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'main.apps.MainConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'main.middleware.VisitorMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'dspace.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
'main.context_processors.site_settings',
],
},
},
]
WSGI_APPLICATION = 'dspace.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.environ.get('DJANGO_DB_PATH', BASE_DIR / 'db.sqlite3'),
}
}
AUTH_USER_MODEL = 'main.CustomUser'
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',
},
]
LANGUAGE_CODE = 'ru-ru'
TIME_ZONE = 'Europe/Moscow'
USE_I18N = True
USE_TZ = True
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
# Хеширование статических файлов в production
if not DEBUG:
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Yandex SmartCaptcha Settings
SMARTCAPTCHA_CLIENT_KEY = os.environ.get('SMARTCAPTCHA_CLIENT_KEY', '')
SMARTCAPTCHA_SERVER_KEY = os.environ.get('SMARTCAPTCHA_SERVER_KEY', '')
# Telegram Bot Settings
TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN', '')
TELEGRAM_CHANNEL_ID = os.environ.get('TELEGRAM_CHANNEL_ID', '')
# AlertBot (Telegram) — уведомления владельцу о новых сообщениях с формы обратной связи
ALERTBOT_TOKEN = os.environ.get('ALERTBOT_TOKEN', '')
ALERTBOT_CHAT_ID = os.environ.get('ALERTBOT_CHAT_ID', '')
# VK API Settings
VK_ACCESS_TOKEN = os.environ.get('VK_ACCESS_TOKEN', '')
VK_GROUP_ID = os.environ.get('VK_GROUP_ID', '')
# Email Settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST', 'smtp.yandex.ru')
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 465))
EMAIL_USE_SSL = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '')
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', '')
CONTACT_EMAIL = os.environ.get('CONTACT_EMAIL', '')
# Site Settings
SITE_NAME = 'deev.space'
SITE_AUTHOR = 'Деев Егор Викторович'
SITE_DESCRIPTION = 'Персональный сайт backend-разработчика'
# Session Settings
SESSION_COOKIE_AGE = 31536000 # 1 year
SESSION_COOKIE_SECURE = not DEBUG
CSRF_COOKIE_SECURE = not DEBUG
# Security Settings (Production)
if not DEBUG:
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_SSL_REDIRECT = os.environ.get('DJANGO_SECURE_SSL_REDIRECT', 'True') == 'True'
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# Logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
'file': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': BASE_DIR / 'logs' / 'django.log',
'formatter': 'verbose',
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['console'] if DEBUG else ['file', 'console'],
'level': 'INFO',
},
'main': {
'handlers': ['console'] if DEBUG else ['file', 'console'],
'level': 'DEBUG' if DEBUG else 'INFO',
},
},
}
# Create logs directory
(BASE_DIR / 'logs').mkdir(exist_ok=True)