mirror of
https://github.com/lemeow125/DRF_Template.git
synced 2025-09-18 13:39:56 +08:00
Move to uv/pyproject and overhaul project structure
This commit is contained in:
commit
fbb76f8196
26 changed files with 1981 additions and 0 deletions
132
src/core/config/models.py
Normal file
132
src/core/config/models.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
"""
|
||||
Common model schemas
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Literal
|
||||
from datetime import timedelta
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
StrictStr,
|
||||
EmailStr,
|
||||
Field,
|
||||
field_validator,
|
||||
model_validator,
|
||||
)
|
||||
from pydantic_extra_types.timezone_name import TimeZoneName
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
"""
|
||||
Pydantic Configuration model for Django
|
||||
"""
|
||||
|
||||
SECRET_KEY: StrictStr = Field(
|
||||
min_length=32, description="Secret key for the API", required=True
|
||||
)
|
||||
DEBUG: bool = Field(default=False, description="API debug mode")
|
||||
TIMEZONE: TimeZoneName = "UTC"
|
||||
CORS_ORIGINS: list[StrictStr] = Field(
|
||||
description="Allowed CORS origins for API.", default_factory=list
|
||||
)
|
||||
ALLOWED_HOSTS: list[StrictStr] = Field(
|
||||
description="Allowed hosts by the API.", default_factory=list
|
||||
)
|
||||
USE_TZ: bool = Field(
|
||||
required=True,
|
||||
default=True,
|
||||
description="Whether the backend API defaults to using timezone-aware datetimes.",
|
||||
)
|
||||
DJANGO_LOG_LEVEL: Literal["INFO", "DEBUG"] = "INFO"
|
||||
SERVE_MEDIA_LOCALLY: bool = Field(
|
||||
default=False,
|
||||
description="Whether to serve media files locally as oppossed to using a cloud storage solution.",
|
||||
)
|
||||
SMTP_HOST: StrictStr = Field(
|
||||
required=True, description="SMTP server address")
|
||||
SMTP_PORT: int = Field(
|
||||
default=587, description="SMTP server port (default: 587)")
|
||||
SMTP_USE_TLS: bool = Field(
|
||||
default=True, description="Whether to use TLS for SMTP connections"
|
||||
)
|
||||
SMTP_AUTH_USERNAME: StrictStr = Field(
|
||||
required=True, description="SMTP authentication username"
|
||||
)
|
||||
SMTP_AUTH_PASSWORD: StrictStr = Field(
|
||||
required=True, description="SMTP authentication password"
|
||||
)
|
||||
SMTP_FROM_ADDRESS: EmailStr = Field(
|
||||
required=True, description="SMTP from email address"
|
||||
)
|
||||
ACCESS_TOKEN_LIFETIME_MINUTES: timedelta = Field(
|
||||
default=timedelta(minutes=240), description="Access token lifetime in minutes"
|
||||
)
|
||||
REFRESH_TOKEN_LIFETIME_DAYS: timedelta = Field(
|
||||
default=timedelta(days=3), description="Refresh token lifetime in days"
|
||||
)
|
||||
|
||||
@field_validator("CORS_ORIGINS", "ALLOWED_HOSTS", mode="before")
|
||||
def parse_list(cls, v):
|
||||
"""
|
||||
Splits a comma-separated string into a list.
|
||||
"""
|
||||
if isinstance(v, str):
|
||||
return v.split(",")
|
||||
return v
|
||||
|
||||
@field_validator("ACCESS_TOKEN_LIFETIME_MINUTES", mode="before")
|
||||
def parse_timedelta_minutes(cls, v):
|
||||
"""
|
||||
Parse integer values into timedelta objects.
|
||||
"""
|
||||
if isinstance(v, str):
|
||||
return timedelta(minutes=int(v))
|
||||
return v
|
||||
|
||||
@field_validator("REFRESH_TOKEN_LIFETIME_DAYS", mode="before")
|
||||
def parse_timedelta_days(cls, v):
|
||||
"""
|
||||
Parse integer values into timedelta objects.
|
||||
"""
|
||||
if isinstance(v, str):
|
||||
return timedelta(days=int(v))
|
||||
return v
|
||||
|
||||
@model_validator(mode="after")
|
||||
def derive_token_lifetimes(cls, v):
|
||||
"""
|
||||
Sets the appropriate log level based on the DEBUG setting.
|
||||
"""
|
||||
if v.DEBUG:
|
||||
v.DJANGO_LOG_LEVEL = "DEBUG"
|
||||
else:
|
||||
v.DJANGO_LOG_LEVEL = "INFO"
|
||||
return v
|
||||
|
||||
@model_validator(mode="after")
|
||||
def derive_allowed_hosts(cls, v):
|
||||
"""
|
||||
Extracts additional hostnames from CORS_ORIGINS to append to ALLOWED_HOSTS.
|
||||
"""
|
||||
|
||||
cors_origins = v.CORS_ORIGINS
|
||||
allowed_hosts = set(v.ALLOWED_HOSTS or [])
|
||||
|
||||
for origin in cors_origins:
|
||||
match = re.match(r"https?://([^/]+)", origin)
|
||||
if match and match.group(1): # Ensure match.group(1) is not empty
|
||||
allowed_hosts.add(match.group(1))
|
||||
|
||||
v.ALLOWED_HOSTS = list(allowed_hosts)
|
||||
return v
|
||||
|
||||
@model_validator(mode="after")
|
||||
def derive_log_level(cls, v):
|
||||
"""
|
||||
Sets the appropriate log level based on the DEBUG setting.
|
||||
"""
|
||||
if v.DEBUG:
|
||||
v.DJANGO_LOG_LEVEL = "DEBUG"
|
||||
else:
|
||||
v.DJANGO_LOG_LEVEL = "INFO"
|
||||
return v
|
Loading…
Add table
Add a link
Reference in a new issue