Files
2026-hypn0-site/hypn0/hypn0/settings.py
T

228 lines
9.2 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 hypn0 project.
Generated by 'django-admin startproject' using Django 6.0.8.
For more information on this file, see
https://docs.djangoproject.com/en/6.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/6.0/ref/settings/
"""
from pathlib import Path
from django.dispatch import receiver
from django.db.backends.signals import connection_created
import environ
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Read environment variables from .env file
env = environ.Env()
environ.Env.read_env(os.path.join(BASE_DIR.parent, '.env'))
def _normalize_admin_url(value: str) -> str:
"""Приводит URL админки к виду `segment/` без ведущего слэша."""
normalized = value.strip().lstrip('/')
if not normalized:
return 'admin/'
if not normalized.endswith('/'):
normalized += '/'
return normalized
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('DJANGO_SECRET_KEY', default='DJANGO-INSECURE-CHANGE-ME!')
ADMIN_URL = _normalize_admin_url(env('ADMIN_URL', default='admin/'))
# ВНИМАНИЕ: не запускайте с отладкой в продакшен
DEBUG = env.bool('DJANGO_DEBUG', default=True)
# Хосты, на которых будет работать сайт
ALLOWED_HOSTS = env.list(
'DJANGO_ALLOWED_HOSTS',
default=['127.0.0.1', 'localhost', 'hypn0.ru'],
)
# CSRF для всех хостов которым доверяем отправлять входящие запросы
CSRF_TRUSTED_ORIGINS = env.list('DJANGO_CSRF_TRUSTED_ORIGINS', default=[])
# Внутренние адреса для debug toolbar: локальный браузер и loopback (на будущее, если подключим Debug Toolbar)
INTERNAL_IPS = env.list('DJANGO_INTERNAL_IPS', default=['127.0.0.1', '::1'])
# Настройки сообщений об ошибках когда все упало и т.п.
ADMINS = tuple(
tuple(item.split(':', 1))
for item in env.list('DJANGO_ADMINS', default=['S.Erjemin:erjemin@gmail.com'])
)
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'hypn0_site.apps.Hypn0SiteConfig'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'hypn0.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'hypn0_site.context_processors.site_context',
],
},
},
]
WSGI_APPLICATION = 'hypn0.wsgi.application'
# Database
# https://docs.djangoproject.com/en/6.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR.parent.joinpath('database', env('DJANGO_SQLITE_NAME', default='hypn0-db.sqlite3')),
'OPTIONS': {
'timeout': 20,
},
}
}
# Размер первичного ключа по умолчанию
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Параметры SQLite, чтобы дев-окружение не падало на `database is locked`.
# WAL и busy_timeout уменьшают конфликты при чтении/записи, а synchronous=NORMAL
# делает SQLite чуть менее параноидальной, но более живой для локальной разработки.
SQLITE_BUSY_TIMEOUT_MS = 20_000
SQLITE_JOURNAL_MODE = 'WAL'
SQLITE_SYNCHRONOUS = 'NORMAL'
@receiver(connection_created)
def _configure_sqlite_connection(sender, connection, **kwargs):
"""
Настраиваем SQLite сразу после открытия соединения.
Это нужно, чтобы:
- уменьшить число ошибок `database is locked`;
- позволить чтению и записи меньше мешать друг другу;
- сделать dev-среду более терпимой к поиску.
"""
if connection.vendor != 'sqlite':
return
with connection.cursor() as cursor:
cursor.execute(f'PRAGMA journal_mode={SQLITE_JOURNAL_MODE};')
cursor.execute(f'PRAGMA synchronous={SQLITE_SYNCHRONOUS};')
cursor.execute(f'PRAGMA busy_timeout={SQLITE_BUSY_TIMEOUT_MS};')
# Password validation
# https://docs.djangoproject.com/en/6.0/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', },
]
# Internationalization
# https://docs.djangoproject.com/en/6.0/topics/i18n/
LANGUAGE_CODE = 'ru-RU' # <--------- RUSSIAN
# TIME_ZONE = 'Etc/GMT+3' #
TIME_ZONE = 'Europe/Istanbul' #
USE_I18N = True
USE_TZ = True # учитывать часовой пояс
FIRST_DAY_OF_WEEK = 1 # неделя начинается с понедельника
DEFAULT_CHARSET = 'utf-8'
# Настройки почтового сервера и базы данных читаются одинаково для всех окружений.
EMAIL_HOST = env('DJANGO_EMAIL_HOST', default='smtp.mail.ru') # SMTP server
EMAIL_PORT = env.int('DJANGO_EMAIL_PORT', default=2525) # для SSL/https
EMAIL_HOST_USER = env('DJANGO_EMAIL_HOST_USER', default='') # login or ''
EMAIL_HOST_PASSWORD = env('DJANGO_EMAIL_HOST_PASSWORD', default='') # password
EMAIL_FROM = env('DJANGO_EMAIL_FROM', default=EMAIL_HOST_USER) # мейл, от имени которого отправляются письма
SERVER_EMAIL = DEFAULT_FROM_EMAIL = EMAIL_FROM
EMAIL_USE_TLS = True
EMAIL_SUBJECT_PREFIX = 'HYPN0 >> ' # префикс для оповещений об ошибках и необработанных исключениях
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/6.0/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
# Локальные каталоги проекта: медиа и статика лежат рядом в `public`.
PUBLIC_DIR = BASE_DIR.parent.joinpath('public')
MEDIA_ROOT = PUBLIC_DIR.joinpath('media')
STATICFILES_DIRS = [PUBLIC_DIR.joinpath('static')]
STATIC_ROOT = PUBLIC_DIR.joinpath('staticfiles')
# Django 5 требует явное описание хранилищ.
# `default` нужен для загружаемых файлов (filer, FileField, ImageField) и смотрит в `MEDIA_ROOT`.
# `staticfiles` остаётся отдельно: в dev используется обычная статика Django, в prod — WhiteNoise.
STORAGES = {
'default': {
'BACKEND': 'django.core.files.storage.FileSystemStorage',
'OPTIONS': {
'location': MEDIA_ROOT,
},
},
}
if DEBUG:
# В деве оставляем стандартную отдачу статики Django без WhiteNoise.
STORAGES['staticfiles'] = {
'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage',
}
# Django Debug Toolbar нужен только в dev
def _show_debug_toolbar(request):
"""Скрывает debug toolbar внутри админки Django"""
return not request.path.startswith(f'/{ADMIN_URL}')
INSTALLED_APPS.append('debug_toolbar')
MIDDLEWARE.insert(1, 'debug_toolbar.middleware.DebugToolbarMiddleware')
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': _show_debug_toolbar,
}
else:
# В продакшене WhiteNoise обслуживает собранную статику и файлы из `public`.
MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
STORAGES['staticfiles'] = {
'BACKEND': 'whitenoise.storage.CompressedManifestStaticFilesStorage',
}
# Конфигурация WhiteNoise для обслуживания статических файлов и файлов из /public (например,
# robots.txt, favicon.ico и т.п.)
WHITENOISE_ROOT = PUBLIC_DIR