import os from pathlib import Path from django.utils.translation import gettext_lazy as _ from django.urls import re_path # 构建路径,如 BASE_DIR / 'subdir' BASE_DIR = Path(__file__).resolve().parent.parent INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Make sure this is here only once 'widget_tweaks', 'core.apps.CoreConfig', 'links', 'tailwind', 'new_theme', 'simplemde', 'markdown', # 只需要基本的markdown包 'netscan', 'nginxmon', 'routermon', ] ROOT_URLCONF = 'core.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(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', 'core.context_processors.build_info', ], }, }, ] # ... 其他设置 ... # 添加以下基本设置(如果尚未存在) SECRET_KEY = 'your-secret-key-here' # 请更改为一个安全的随机值 DEBUG = os.environ.get('DEBUG', 'True').lower() in ('true', '1', 'yes') ALLOWED_HOSTS = ['*'] # 数据库设置(使用默认的SQLite配置) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': '/app/data/db.sqlite3', # Updated path 'NAME': BASE_DIR / 'data/db.sqlite3', } } # 静态文件设置 STATIC_EXTRA_DIR = 'static' STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATICFILES_DIRS = [ os.path.join(BASE_DIR, STATIC_EXTRA_DIR), ] # 默认自动字段类型 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' LANGUAGES = [ ('en', _('English')), ('zh-hans', _('Simplified Chinese')), ] LOCALE_PATHS = [ BASE_DIR / 'locale', ] LANGUAGE_CODE = 'en' # 设置默认语言为英语 USE_I18N = True USE_L10N = True USE_TZ = True # ... 其他设置 ... ROOT_URLCONF = 'core.urls' # ... 其他设置 ... TAILWIND_APP_NAME = 'new_theme' INTERNAL_IPS = [ "127.0.0.1", ] # Add this at the end of the file STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' CSRF_TRUSTED_ORIGINS = os.environ.get('CSRF_TRUSTED_ORIGINS', 'http://localhost:8000').split(',') # Redis cache REDIS_URL = os.environ.get('REDIS_URL', 'redis://192.168.1.2:6379/0') CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': REDIS_URL, 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', }, 'TIMEOUT': 300, } } # Store sessions in Redis instead of the database SESSION_ENGINE = 'django.contrib.sessions.backends.cache' SESSION_CACHE_ALIAS = 'default' # SimpleMDE 配置 SIMPLEMDE_OPTIONS = { 'placeholder': 'Type here...', 'status': False, 'autosave': { 'enabled': True, 'delay': 10000, }, } MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'data', 'media') MUSIC_ROOT = os.path.join(BASE_DIR, 'data', 'music') # File uploads folder — override via FILE_UPLOADS_FOLDER env var. # Defaults to ~/Downloads locally; set to /uploads on k8s. FILE_UPLOADS_FOLDER = os.environ.get('FILE_UPLOADS_FOLDER', os.path.expanduser('~/Downloads')) IMAGES_FOLDER = os.environ.get('IMAGES_FOLDER', os.path.expanduser('~/Pictures')) LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'root': { 'handlers': ['console'], 'level': 'INFO', }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'INFO', 'propagate': False, }, }, } LANGUAGE_URL_MAP = { 'en': 'en', 'zh-hans': 'zh', } # 添加这个配置来排除 API URLs 的语言重定向 LOCALE_PATHS = [ os.path.join(BASE_DIR, 'locale'), ] PREFIX_DEFAULT_LANGUAGE = True # 修改这里,使用简单的字符串模式而不是 re_path LOCALE_INDEPENDENT_PATHS = [ 'api/', # 只需要一个简单的字符串前缀 ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'core.middleware.CustomLocaleMiddleware', # 使用自定义中间件 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', ], 'DEFAULT_AUTHENTICATION_CLASSES': [], 'DEFAULT_PERMISSION_CLASSES': [], 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10, 'UNAUTHENTICATED_USER': None, } # Time zone setting TIME_ZONE = 'Australia/Melbourne' USE_TZ = True # Media files configuration MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'data', 'media') # Ensure media files are served in all environments SERVE_MEDIA = True # Cloudflare R2 Settings R2_ENDPOINT_URL = os.environ.get('R2_ENDPOINT_URL') R2_ACCESS_KEY_ID = os.environ.get('R2_ACCESS_KEY_ID') R2_SECRET_ACCESS_KEY = os.environ.get('R2_SECRET_ACCESS_KEY') R2_BUCKET_NAME = os.environ.get('R2_BUCKET_NAME') R2_CUSTOM_DOMAIN = os.environ.get('R2_CUSTOM_DOMAIN') # Crawl4AI Configuration CRAWL4AI_API_URL = os.environ.get('CRAWL4AI_API_URL', 'https://crawl-api.junv.cc') CRAWL4AI_ENABLED = os.environ.get('CRAWL4AI_ENABLED', 'True').lower() in ('true', '1', 'yes') # Build metadata (injected at Docker image build time) BUILD_TIME = os.environ.get('BUILD_TIME', '') BUILD_VERSION = os.environ.get('BUILD_VERSION', '') # For debugging LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', }, }, 'loggers': { 'links': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, }, }