rtc_backend/config/settings.py
repair-agent f1bead86f6
Some checks failed
Build and Deploy Backend / build-and-deploy (push) Failing after 56s
fix music
2026-02-12 17:35:54 +08:00

251 lines
8.4 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 RTC_DEMO project.
"""
import os
from pathlib import Path
from datetime import timedelta
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / '.env')
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-dev-key-change-in-production')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DJANGO_DEBUG', 'True').lower() == 'true'
ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', '*').split(',')
# 纯 API 服务,禁用 APPEND_SLASH 避免 POST/PUT/PATCH/DELETE 请求因缺少尾部斜杠而触发 RuntimeError
APPEND_SLASH = False
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party
'rest_framework',
'rest_framework_simplejwt',
'corsheaders',
'drf_spectacular',
# Local apps
'apps.users',
'apps.spirits',
'apps.devices',
'apps.inventory',
'apps.admins',
'apps.stories',
'apps.music',
'apps.notifications',
'apps.system',
]
MIDDLEWARE = [
'utils.middleware.ExceptionReportMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'utils.middleware.TrailingSlashMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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 = 'config.wsgi.application'
# Database - MySQL via PyMySQL
import pymysql
pymysql.version_info = (2, 2, 1, 'final', 0) # Django 6.x requires mysqlclient >= 2.2.1
pymysql.install_as_MySQLdb()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get('DB_NAME', 'rtc'),
'USER': os.environ.get('DB_USER', 'rtc'),
'PASSWORD': os.environ.get('DB_PASSWORD', 'JogNQdtrd3WY8CBCAiYfYEGx'),
'HOST': os.environ.get('DB_HOST', 'rm-7xv1uaw910558p1788o.mysql.rds.aliyuncs.com'),
'PORT': os.environ.get('DB_PORT', '3306'),
'OPTIONS': {
'charset': 'utf8mb4',
},
'TEST': {
'NAME': 'rtc', # 使用现有数据库进行测试
},
}
}
# Redis Cache
REDIS_PASSWORD = os.environ.get('REDIS_PASSWORD', 'vAhRnAA6VMco')
REDIS_URL = os.environ.get('REDIS_URL', f'redis://:{REDIS_PASSWORD}@r-7xvat0vez5clwbzk5vpd.redis.rds.aliyuncs.com:6379/8')
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': REDIS_URL,
}
}
# Password validation
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'},
]
# Custom User Model
AUTH_USER_MODEL = 'users.User'
# Internationalization
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
# Static files
STATIC_URL = 'static/'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# CORS Settings
CORS_ALLOW_ALL_ORIGINS = DEBUG
CORS_ALLOWED_ORIGINS = os.environ.get('CORS_ALLOWED_ORIGINS', '').split(',') if not DEBUG else []
# REST Framework
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
'EXCEPTION_HANDLER': 'utils.exceptions.custom_exception_handler',
}
# JWT Settings
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=7),
'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
'ROTATE_REFRESH_TOKENS': True,
'ALGORITHM': 'HS256',
'AUTH_HEADER_TYPES': ('Bearer',),
}
# Aliyun 公共配置OSS 和 SMS 共用)
ALIYUN_ACCESS_KEY_ID = os.environ.get('ALIYUN_ACCESS_KEY_ID', 'LTAI5tBGAkR2rra2prTAX9yc')
ALIYUN_ACCESS_KEY_SECRET = os.environ.get('ALIYUN_ACCESS_KEY_SECRET', 'U1z3d0p5saPRD5sCxVooJYSjxSAmKB')
# Aliyun OSS Settings
ALIYUN_OSS = {
'ACCESS_KEY_ID': os.environ.get('OSS_ACCESS_KEY_ID', ALIYUN_ACCESS_KEY_ID),
'ACCESS_KEY_SECRET': os.environ.get('OSS_ACCESS_KEY_SECRET', ALIYUN_ACCESS_KEY_SECRET),
'ENDPOINT': os.environ.get('OSS_ENDPOINT', 'oss-cn-beijing.aliyuncs.com'),
'BUCKET_NAME': os.environ.get('OSS_BUCKET_NAME', 'qy-rtc'),
'CUSTOM_DOMAIN': os.environ.get('OSS_CUSTOM_DOMAIN', ''),
}
# Aliyun SMS Settings
ALIYUN_SMS = {
'ACCESS_KEY_ID': os.environ.get('SMS_ACCESS_KEY_ID', ALIYUN_ACCESS_KEY_ID),
'ACCESS_KEY_SECRET': os.environ.get('SMS_ACCESS_KEY_SECRET', ALIYUN_ACCESS_KEY_SECRET),
'SIGN_NAME': os.environ.get('SMS_SIGN_NAME', '广州气元科技'),
'TEMPLATE_CODE': os.environ.get('SMS_TEMPLATE_CODE', 'SMS_317100048'),
'CODE_LENGTH': 6, # 验证码位数
'CODE_EXPIRE': 300, # 过期时间(秒) 5分钟
'SEND_INTERVAL': 60, # 发送间隔(秒) 60秒
}
# Aliyun Phone Auth (号码认证/一键登录)
ALIYUN_PHONE_AUTH = {
'ACCESS_KEY_ID': os.environ.get('PHONE_AUTH_ACCESS_KEY_ID', ALIYUN_ACCESS_KEY_ID),
'ACCESS_KEY_SECRET': os.environ.get('PHONE_AUTH_ACCESS_KEY_SECRET', ALIYUN_ACCESS_KEY_SECRET),
}
# LLM Settings - Volcengine Ark SDK / 火山引擎豆包 (Story Generation)
LLM_CONFIG = {
'API_KEY': os.environ.get('VOLCENGINE_API_KEY', ''),
'MODEL_NAME': os.environ.get('VOLCENGINE_MODEL_NAME', 'doubao-seed-1-6-lite-251015'),
}
# Swagger/OpenAPI Settings
SPECTACULAR_SETTINGS = {
'TITLE': 'RTC API',
'DESCRIPTION': 'RTC 物联网设备管理平台',
'VERSION': '1.0.0',
'SERVE_INCLUDE_SCHEMA': False,
'COMPONENT_SPLIT_REQUEST': True,
'SWAGGER_UI_SETTINGS': {
'persistAuthorization': True,
'docExpansion': 'list',
},
'TAGS': [
{'name': '认证', 'description': 'App 用户登录、登出、Token 刷新'},
{'name': '用户', 'description': 'App 用户个人信息管理'},
{'name': '设备', 'description': '设备绑定、设置、WiFi 配置'},
{'name': '智能体', 'description': 'AI 智能体 CRUD 和绑定'},
{'name': '故事', 'description': '故事列表、书架管理、生成'},
{'name': '音乐', 'description': '音乐播放列表、收藏、生成'},
{'name': '通知', 'description': '通知列表、已读、删除'},
{'name': '系统', 'description': '意见反馈、版本检查'},
{'name': '管理员-认证', 'description': '管理员登录和个人信息'},
{'name': '管理员-用户管理', 'description': '管理端 App 用户管理'},
{'name': '管理员-账号管理', 'description': '管理员账号 CRUD超级管理员'},
{'name': '管理员-库存', 'description': '设备类型和批次管理'},
],
}
# Logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'root': {
'handlers': ['console'],
'level': 'INFO',
},
}