wag-managment-api-service-v.../ApiEvents/base_request_model.py

124 lines
3.9 KiB
Python

"""
Base request models for API endpoints.
This module provides base request models that can be used across different endpoints
to ensure consistent request handling and validation.
"""
from typing import Dict, Any, Generic, TypeVar, Optional, get_args, get_origin
from pydantic import RootModel, BaseModel, Field, ConfigDict
T = TypeVar("T")
class BaseRequestModel(RootModel[T]):
"""Base model for all API requests.
This model can be extended to create specific request models for different endpoints.
"""
model_config = ConfigDict(
json_schema_extra={"example": {}} # Will be populated by subclasses
)
@classmethod
def model_json_schema(cls, *args, **kwargs):
schema = super().model_json_schema(*args, **kwargs)
if hasattr(cls, "__orig_bases__"):
generic_type = get_args(cls.__orig_bases__[0])[0]
if generic_type and hasattr(generic_type, "model_json_schema"):
type_schema = generic_type.model_json_schema()
if "properties" in type_schema:
schema["properties"] = type_schema["properties"]
if "required" in type_schema:
schema["required"] = type_schema["required"]
if "title" in type_schema:
schema["title"] = type_schema["title"]
if "example" in type_schema:
schema["example"] = type_schema["example"]
elif "properties" in type_schema:
schema["example"] = {
key: prop.get("example", "string")
for key, prop in type_schema["properties"].items()
}
schema["type"] = "object"
return schema
@property
def data(self) -> T:
return self.root
class DictRequestModel(RootModel[Dict[str, Any]]):
"""Request model for endpoints that accept dictionary data."""
model_config = ConfigDict(
json_schema_extra={
"example": {
"key1": "value1",
"key2": "value2",
"nested": {"inner_key": "inner_value"},
}
}
)
@classmethod
def model_json_schema(cls, *args, **kwargs):
schema = super().model_json_schema(*args, **kwargs)
schema.update(
{
"title": "Dictionary Request Model",
"type": "object",
"properties": {
"key1": {"type": "string", "example": "value1"},
"key2": {"type": "string", "example": "value2"},
"nested": {
"type": "object",
"properties": {
"inner_key": {"type": "string", "example": "inner_value"}
},
},
},
"example": {
"key1": "value1",
"key2": "value2",
"nested": {"inner_key": "inner_value"},
},
}
)
return schema
@property
def data(self) -> Dict[str, Any]:
return self.root
class SuccessResponse(BaseModel):
"""Standard success response model."""
token: str = Field(..., example="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
user_info: Dict[str, Any] = Field(
...,
example={
"id": "123",
"username": "john.doe",
"email": "john@example.com",
"role": "user",
},
)
model_config = ConfigDict(
json_schema_extra={
"example": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user_info": {
"id": "123",
"username": "john.doe",
"email": "john@example.com",
"role": "user",
},
}
}
)