Files
fast-next-template/backend/app/schemas/common.py
Felipe Cardoso 2c600290a1 Enhance user management, improve API structure, add database optimizations, and update Docker setup
- Introduced endpoints for user management, including CRUD operations, pagination, and password management.
- Added new schema validations for user updates, password strength, pagination, and standardized error responses.
- Integrated custom exception handling for a consistent API error experience.
- Refined CORS settings: restricted methods and allowed headers, added header exposure, and preflight caching.
- Optimized database: added indexes on `is_active` and `is_superuser` fields, updated column types, enforced constraints, and set defaults.
- Updated `Dockerfile` to improve security by using a non-root user and adding a health check for the application.
- Enhanced tests for database initialization, user operations, and exception handling to ensure better coverage.
2025-10-30 15:43:52 +01:00

140 lines
3.5 KiB
Python

"""
Common schemas used across the API for pagination, responses, etc.
"""
from typing import Generic, TypeVar, List, Optional
from pydantic import BaseModel, Field
from math import ceil
T = TypeVar('T')
class PaginationParams(BaseModel):
"""Parameters for pagination."""
page: int = Field(
default=1,
ge=1,
description="Page number (1-indexed)"
)
limit: int = Field(
default=20,
ge=1,
le=100,
description="Number of items per page (max 100)"
)
@property
def offset(self) -> int:
"""Calculate the offset for database queries."""
return (self.page - 1) * self.limit
@property
def skip(self) -> int:
"""Alias for offset (compatibility with existing code)."""
return self.offset
model_config = {
"json_schema_extra": {
"example": {
"page": 1,
"limit": 20
}
}
}
class PaginationMeta(BaseModel):
"""Metadata for paginated responses."""
total: int = Field(..., description="Total number of items")
page: int = Field(..., description="Current page number")
page_size: int = Field(..., description="Number of items in current page")
total_pages: int = Field(..., description="Total number of pages")
has_next: bool = Field(..., description="Whether there is a next page")
has_prev: bool = Field(..., description="Whether there is a previous page")
model_config = {
"json_schema_extra": {
"example": {
"total": 150,
"page": 1,
"page_size": 20,
"total_pages": 8,
"has_next": True,
"has_prev": False
}
}
}
class PaginatedResponse(BaseModel, Generic[T]):
"""Generic paginated response wrapper."""
data: List[T] = Field(..., description="List of items")
pagination: PaginationMeta = Field(..., description="Pagination metadata")
model_config = {
"json_schema_extra": {
"example": {
"data": [
{"id": "123", "name": "Example Item"}
],
"pagination": {
"total": 150,
"page": 1,
"page_size": 20,
"total_pages": 8,
"has_next": True,
"has_prev": False
}
}
}
}
class MessageResponse(BaseModel):
"""Simple message response."""
success: bool = Field(default=True, description="Operation success status")
message: str = Field(..., description="Human-readable message")
model_config = {
"json_schema_extra": {
"example": {
"success": True,
"message": "Operation completed successfully"
}
}
}
def create_pagination_meta(
total: int,
page: int,
limit: int,
items_count: int
) -> PaginationMeta:
"""
Helper function to create pagination metadata.
Args:
total: Total number of items
page: Current page number
limit: Items per page
items_count: Number of items in current page
Returns:
PaginationMeta object with calculated values
"""
total_pages = ceil(total / limit) if limit > 0 else 0
return PaginationMeta(
total=total,
page=page,
page_size=items_count,
total_pages=total_pages,
has_next=page < total_pages,
has_prev=page > 1
)