import os from datetime import timedelta from pathlib import Path def _env_bool(name: str, default: bool = False) -> bool: raw = os.environ.get(name) if raw is None: return default return raw.strip().lower() in {"1", "true", "yes", "y", "on"} def _env_list(name: str, default: list[str] | None = None) -> list[str]: raw = os.environ.get(name) if raw is None: return default or [] return [part.strip() for part in raw.split(",") if part.strip()] BASE_DIR = Path(__file__).resolve().parent.parent.parent REPO_ROOT = BASE_DIR.parent def _load_env_file(env_path: Path) -> None: if not env_path.exists() or not env_path.is_file(): return for raw_line in env_path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) key = key.strip() if not key or key in os.environ: continue value = value.strip().strip('"').strip("'") os.environ[key] = value _load_env_file(REPO_ROOT / ".env") SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "unsafe-dev-secret-key") DEBUG = _env_bool("DJANGO_DEBUG", default=True) ALLOWED_HOSTS = _env_list("DJANGO_ALLOWED_HOSTS", default=["127.0.0.1","192.168.1.60", "192.168.1.93","localhost","192.168.1.174"]) DATETIME_FORMAT = os.environ.get("DJANGO_DATETIME_FORMAT", "Y-m-d H:i:s") INSTALLED_APPS = [ "simpleui", "corsheaders", "drf_yasg", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", "rest_framework_simplejwt", "apps.iam", "apps.datasets", "apps.annotation", "apps.algorithms", "apps.training", "apps.cloud_terminal.apps.CloudTerminalConfig", "apps.core.apps.CoreConfig", "channels", "django_extensions", ] ASGI_APPLICATION = "config.asgi.application" WSGI_APPLICATION = "config.wsgi.application" 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", "corsheaders.middleware.CorsMiddleware", ] CORS_ALLOWED_ORIGINS = _env_list("DJANGO_CORS_ALLOWED_ORIGINS", default=[ "http://127.0.0.1:3000", "http://localhost:3000", "http://192.168.1.60:3000", "http://192.168.1.93:3000", "ws://192.168.1.60:3000", "ws://192.168.1.93:3000", "ws://localhost:3000", ]) CORS_ALLOW_ALL_ORIGINS = _env_bool("DJANGO_CORS_ALLOW_ALL_ORIGINS", default=False) CSRF_TRUSTED_ORIGINS = _env_list("DJANGO_CSRF_TRUSTED_ORIGINS", default=[]) ROOT_URLCONF = "config.urls" FRONTEND_DIST_DIR = Path( os.environ.get("FRONTEND_DIST_DIR", str(REPO_ROOT / "frontend" / "dist")) ) TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [str(FRONTEND_DIST_DIR)], "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", ], }, } ] REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES": [ "rest_framework.renderers.JSONRenderer", ], "DEFAULT_PARSER_CLASSES": [ "rest_framework.parsers.JSONParser", ], "DEFAULT_AUTHENTICATION_CLASSES": [ "rest_framework_simplejwt.authentication.JWTAuthentication", ], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.AllowAny", ], "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", "PAGE_SIZE": int(os.environ.get("DJANGO_PAGE_SIZE", "10")), "DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.openapi.AutoSchema", "DEFAULT_FILTER_BACKENDS": [ "django_filters.rest_framework.DjangoFilterBackend", ], "DEFAULT_THROTTLE_RATES": { "anon": None, "user": None, }, "DEFAULT_THROTTLE_CLASSES": ( "rest_framework.throttling.AnonRateThrottle", "rest_framework.throttling.UserRateThrottle", ), "EXCEPTION_HANDLER": "rest_framework.views.exception_handler", "DEFAULT_METADATA_CLASS": "rest_framework.metadata.SimpleMetadata", } SIMPLE_JWT = { "ACCESS_TOKEN_LIFETIME": timedelta( minutes=int(os.environ.get("JWT_ACCESS_MINUTES", "60")) ), "REFRESH_TOKEN_LIFETIME": timedelta(days=int(os.environ.get("JWT_REFRESH_DAYS", "1"))), } DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": os.environ.get("DB_NAME", "ai-traindb") or "ai-traindb", "USER": os.environ.get("DB_USER", "postgres") or "postgres", "PASSWORD": os.environ.get("DB_PASSWORD", "Zhengsl321DSA") or "60edrhkdwa1ecd", "HOST": os.environ.get("DB_HOST", "127.0.0.1") or "127.0.0.1", "PORT": os.environ.get("DB_PORT", "5432") or "5432", }, } DB_ENGINE = os.environ.get("DB_ENGINE") if DB_ENGINE: if DB_ENGINE == "django.db.backends.sqlite3": sqlite_name = os.environ.get("DB_NAME") or str(BASE_DIR / "db.sqlite3") DATABASES = {"default": {"ENGINE": DB_ENGINE, "NAME": sqlite_name}} else: DATABASES["default"]["ENGINE"] = DB_ENGINE SM4_PRIVATE_KEY = os.environ.get("SM4_PRIVATE_KEY", "a8b502da70405867") private_key = SM4_PRIVATE_KEY 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 = "zh-hans" TIME_ZONE = "Asia/Shanghai" USE_I18N = True USE_TZ = True STATIC_URL = "/static/" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" LOGOUT_REDIRECT_URL = "/account/login/" DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024 FILE_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024 MODEL_ROOT_PATH = str("D:/07_Temp/model_space") FILESPACE_ROOT_PATH = str("D:/07_Temp/train_workspace") TRAIN_LOG_DIR = os.environ.get("TRAIN_LOG_DIR", str(Path(FILESPACE_ROOT_PATH) / "log")) MEDIA_URL = os.environ.get("MEDIA_URL", "/image/") MEDIA_ROOT = os.environ.get("MEDIA_ROOT", FILESPACE_ROOT_PATH) TASK_CALL_BACK_URL = os.environ.get("TASK_CALL_BACK_URL", "http://localhost:8000/server/") ANNOTATION_SERVICE_INFER_URL = os.environ.get( "ANNOTATION_SERVICE_INFER_URL", "http://172.16.31.195:8090/infer", ) AUTO_ANNOTATE_MAX_WORKERS = int(os.environ.get("AUTO_ANNOTATE_MAX_WORKERS", "2")) AUTO_ANNOTATE_SCORE_THRESHOLD = float(os.environ.get("AUTO_ANNOTATE_SCORE_THRESHOLD", "0.4")) VIDEO_FRAME_INTERVAL = int(os.environ.get("VIDEO_FRAME_INTERVAL", "10")) DEFAULT_CHARSET = "UTF-8" REDIS_URL = os.environ.get("REDIS_URL") if REDIS_URL: CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": {"hosts": [REDIS_URL]}, } } else: CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", } } # ── MinIO 对象存储配置 ───────────────────────────── MINIO_ENDPOINT = os.environ.get("MINIO_ENDPOINT", "127.0.0.1:9000") MINIO_PRESIGN_ENDPOINT = os.environ.get("MINIO_PRESIGN_ENDPOINT","192.168.1.60:9000") MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY", "admin") MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY", "zhengsl2026") MINIO_SECURE = _env_bool("MINIO_SECURE", default=False) MINIO_DEFAULT_BUCKET = os.environ.get("MINIO_DEFAULT_BUCKET", "ai-trainprediction") MINIO_PRESIGN_EXPIRES = int(os.environ.get("MINIO_PRESIGN_EXPIRES", "3600"))