Files
2025-12-09 14:46:02 +08:00

352 lines
12 KiB
Python
Raw Permalink 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 hertz_server_django project.
Generated by 'django-admin startproject' using Django 5.2.6.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""
import os
from pathlib import Path
from decouple import config
# 修复DRF的ip_address_validators函数
def fix_drf_ip_validators():
"""
修复DRF的ip_address_validators函数返回值问题
"""
try:
from rest_framework import fields
# 保存原始函数
original_ip_address_validators = fields.ip_address_validators
def fixed_ip_address_validators(protocol, unpack_ipv4):
"""
修复后的ip_address_validators函数确保返回两个值
"""
validators = original_ip_address_validators(protocol, unpack_ipv4)
# 如果只返回了validators添加默认的error_message
if isinstance(validators, list):
return validators, 'Enter a valid IP address.'
else:
# 如果已经返回了两个值,直接返回
return validators
# 应用猴子补丁
fields.ip_address_validators = fixed_ip_address_validators
except ImportError:
# 如果DRF未安装忽略错误
pass
# 应用修复
fix_drf_ip_validators()
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY', default='django-insecure-0a1bx*8!97l^4z#ml#ufn_*9ut*)zlso$*k-g^h&(2=p@^51md')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=True, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1', cast=lambda v: [s.strip() for s in v.split(',')])
# Database engine configuration (sqlite/mysql) with backward compatibility
# Prefer `DB_ENGINE` env var; fallback to legacy `USE_REDIS_AS_DB`
DB_ENGINE = config('DB_ENGINE', default=None)
USE_REDIS_AS_DB = config('USE_REDIS_AS_DB', default=True, cast=bool)
if DB_ENGINE is None:
DB_ENGINE = 'sqlite' if USE_REDIS_AS_DB else 'mysql'
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
'corsheaders',
'channels',
'drf_spectacular',
# 必备注册的app不要删
'hertz_demo', # 初始化演示模块
'hertz_studio_django_captcha', # 验证码模块
'hertz_studio_django_auth', # 权限模块
'hertz_studio_django_system_monitor', # 系统监测模块
'hertz_studio_django_log', # 日志管理模块
'hertz_studio_django_notice', # 通知模块
# ======在下面导入你需要的app======
'hertz_studio_django_ai', #ai聊天模块
'hertz_studio_django_kb', # 知识库 ai和kb库是相互绑定的
'hertz_studio_django_wiki', # 文章模块
'hertz_studio_django_yolo', # YOLO目标检测模块
'hertz_studio_django_yolo_train', # Yolo训练模块
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'hertz_studio_django_auth.utils.middleware.AuthMiddleware', # 权限认证中间件
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'hertz_server_django.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',
],
},
},
]
WSGI_APPLICATION = 'hertz_server_django.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
if DB_ENGINE == 'sqlite':
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'data/db.sqlite3',
}
}
# Use Redis-backed sessions when on SQLite (optional, keeps prior behavior)
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
elif DB_ENGINE == 'mysql':
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': config('DB_NAME', default='hertz_server'),
'USER': config('DB_USER', default='root'),
'PASSWORD': config('DB_PASSWORD', default='root'),
'HOST': config('DB_HOST', default='localhost'),
'PORT': config('DB_PORT', default='3306'),
'OPTIONS': {
'charset': 'utf8mb4',
},
}
}
else:
# Fallback to SQLite for unexpected values
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'data/db.sqlite3',
}
}
# Redis
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': config('REDIS_URL', default='redis://127.0.0.1:6379/0'),
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
# Password validation
# https://docs.djangoproject.com/en/5.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',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Media files (User uploaded files)
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Django REST Framework configuration
# 使用自定义AuthMiddleware进行认证不使用DRF的认证和权限系统
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': [], # 不使用DRF认证类
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny', # 所有接口默认允许访问由AuthMiddleware控制权限
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
# Spectacular (OpenAPI 3.0) configuration
SPECTACULAR_SETTINGS = {
'TITLE': 'Hertz Server API',
'DESCRIPTION': 'API documentation for Hertz Server Django project',
'VERSION': '1.0.0',
'SERVE_INCLUDE_SCHEMA': False,
'COMPONENT_SPLIT_REQUEST': True,
'SCHEMA_PATH_PREFIX': '/api/',
}
# CORS configuration
CORS_ALLOWED_ORIGINS = config(
'CORS_ALLOWED_ORIGINS',
default='http://localhost:3000,http://127.0.0.1:3000',
cast=lambda v: [s.strip() for s in v.split(',')]
)
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = config('CORS_ALLOW_ALL_ORIGINS', default=False, cast=bool)
# Captcha settings
CAPTCHA_IMAGE_SIZE = (
config('CAPTCHA_IMAGE_SIZE_WIDTH', default=120, cast=int),
config('CAPTCHA_IMAGE_SIZE_HEIGHT', default=50, cast=int)
)
CAPTCHA_LENGTH = config('CAPTCHA_LENGTH', default=4, cast=int)
CAPTCHA_TIMEOUT = config('CAPTCHA_TIMEOUT', default=5, cast=int) # minutes
CAPTCHA_FONT_SIZE = config('CAPTCHA_FONT_SIZE', default=40, cast=int)
CAPTCHA_BACKGROUND_COLOR = config('CAPTCHA_BACKGROUND_COLOR', default='#ffffff')
CAPTCHA_FOREGROUND_COLOR = config('CAPTCHA_FOREGROUND_COLOR', default='#000000')
# 验证码词典文件路径
CAPTCHA_WORDS_DICTIONARY = str(BASE_DIR / 'captcha_words.txt')
# 验证码挑战函数配置
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' # 默认使用随机字符
# 数学验证码配置
CAPTCHA_MATH_CHALLENGE_OPERATOR = '+-*'
# 验证码噪声和过滤器
CAPTCHA_NOISE_FUNCTIONS = (
'captcha.helpers.noise_arcs',
'captcha.helpers.noise_dots',
)
CAPTCHA_FILTER_FUNCTIONS = (
'captcha.helpers.post_smooth',
)
# Email configuration
EMAIL_BACKEND = config('EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')
EMAIL_HOST = config('EMAIL_HOST', default='smtp.qq.com')
EMAIL_PORT = config('EMAIL_PORT', default=465, cast=int)
EMAIL_USE_SSL = config('EMAIL_USE_SSL', default=True, cast=bool)
EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=False, cast=bool)
EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='563161210@qq.com')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='')
DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', default='563161210@qq.com')
# 注册邮箱验证码开关0=关闭1=开启)
REGISTER_EMAIL_VERIFICATION = config('REGISTER_EMAIL_VERIFICATION', default=0, cast=int)
# Channels configuration for WebSocket support
ASGI_APPLICATION = 'hertz_server_django.asgi.application'
# Channel layers configuration
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [config('REDIS_URL', default='redis://127.0.0.1:6379/2')],
},
},
}
# 自定义用户模型
AUTH_USER_MODEL = 'hertz_studio_django_auth.HertzUser'
# JWT配置
JWT_SECRET_KEY = config('JWT_SECRET_KEY', default=SECRET_KEY)
JWT_ALGORITHM = 'HS256'
JWT_ACCESS_TOKEN_LIFETIME = config('JWT_ACCESS_TOKEN_LIFETIME', default=60 * 60 * 24, cast=int) # 24小时
JWT_REFRESH_TOKEN_LIFETIME = config('JWT_REFRESH_TOKEN_LIFETIME', default=60 * 60 * 24 * 7, cast=int) # 7天
# 权限系统配置
HERTZ_AUTH_SETTINGS = {
'SUPER_ADMIN_PERMISSIONS': ['*'], # 超级管理员拥有所有权限
'DEFAULT_PERMISSIONS': [], # 默认权限
}
# AuthMiddleware配置 - 不需要登录验证的URL模式支持正则表达式
NO_AUTH_PATTERNS = config(
'NO_AUTH_PATTERNS',
default=r'^/api/auth/login/?$,^/api/auth/register/?$,^/api/auth/email/code/?$,^/api/auth/send-email-code/?$,^/api/auth/password/reset/?$,^/api/captcha/.*$,^/api/docs/.*$,^/api/redoc/.*$,^/api/schema/.*$,^/admin/.*$,^/static/.*$,^/media/.*$,^/demo/.*$,^/websocket/.*$,^/api/system/.*$',
cast=lambda v: [s.strip() for s in v.split(',')]
)
# 密码加密配置
PASSWORD_HASHERS = [
'hertz_studio_django_utils.crypto.MD5PasswordHasher', # 使用MD5加密
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]