用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/agusmdev/fullstack-ai-template --skill fastapi-core-schemas命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Codebase health scanner and technical debt tracker. Use when the user asks about code quality, technical debt, dead code, large files, god classes, duplicate functions, code smells, naming issues, import cycles, or coupling problems. Also use when asked for a health score, what to fix next, or to create a cleanup plan. Supports 29 languages.
Configure Alembic for async SQLAlchemy migrations with PostgreSQL
Create FastAPI application factory with lifespan, middleware, pagination, and router configuration
基于 SOC 职业分类
正在显示 SKILL.md
| name | fastapi-core-schemas |
| description | Create Pydantic v2 base schemas for request validation and response serialization in FastAPI |
This skill covers creating base Pydantic v2 schemas for consistent request/response handling across the application.
Create src/app/core/schemas.py:
from datetime import datetime
from uuid import UUID
from pydantic import BaseModel, ConfigDict
class BaseSchema(BaseModel):
"""
Base schema for all Pydantic models.
Configured with:
- from_attributes: Enables ORM mode (read from SQLAlchemy models)
- populate_by_name: Allow using field names or aliases
- str_strip_whitespace: Strip whitespace from string fields
- validate_default: Validate default values
"""
model_config = ConfigDict(
from_attributes=True,
populate_by_name=True,
str_strip_whitespace=True,
validate_default=True,
)
class BaseCreateSchema(BaseSchema):
"""
Base schema for create operations.
Does NOT include id, timestamps, or deleted_at.
Only fields that the client provides when creating a resource.
"""
pass
class ():
():
: UUID
created_at: datetime
updated_at: datetime
():
deleted_at: datetime | =
When creating entity schemas, inherit from the base schemas:
# src/app/items/schemas.py
from uuid import UUID
from pydantic import Field
from app.core.schemas import (
BaseCreateSchema,
BaseUpdateSchema,
BaseResponseSchema,
)
class ItemCreate(BaseCreateSchema):
"""Schema for creating an item."""
name: str = Field(..., min_length=1, max_length=255)
description: str | None = Field(default=None, max_length=5000)
category_id: UUID
class ItemUpdate(BaseUpdateSchema):
"""Schema for updating an item. All fields optional for PATCH."""
name: str | None = Field(default=None, min_length=1, max_length=255)
description: str | None = Field(default=None, max_length=5000)
category_id: UUID | None = None
class ItemResponse(BaseResponseSchema):
"""Schema for item responses."""
name: str
description: str | None
category_id: UUID
| Option | Purpose | Default |
|---|---|---|
from_attributes | Read data from ORM model attributes | False |
populate_by_name | Allow field name or alias | False |
str_strip_whitespace | Strip whitespace from strings | False |
validate_default | Validate default values | False |
strict | Strict type coercion | False |
extra | Handle extra fields: "ignore", "forbid", "allow" | "ignore" |
from pydantic import Field, field_validator, model_validator
class ItemCreate(BaseCreateSchema):
name: str = Field(
..., # Required
min_length=1,
max_length=255,
description="Item name",
examples=["My Item"],
)
price: float = Field(
...,
gt=0, # Greater than 0
le=1000000, # Less than or equal to
description="Item price in USD",
)
tags: list[str] = Field(
default_factory=list,
max_length=10, # Max 10 tags
)
@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
"""Custom name validation."""
if v.lower() == "test":
raise ValueError("Name cannot be 'test'")
return v.title()
@model_validator(mode="after")
def validate_model(self) -> "ItemCreate":
"""Cross-field validation."""
if self.price > 100 and not self.tags:
raise ValueError("Expensive items must have tags")
return self
class CategoryResponse(BaseResponseSchema):
name: str
class ItemWithCategoryResponse(BaseResponseSchema):
"""Item response with nested category."""
name: str
description: str | None
category: CategoryResponse # Nested schema
For list endpoints with metadata:
from typing import Generic, TypeVar
from pydantic import BaseModel
T = TypeVar("T")
class ListResponse(BaseModel, Generic[T]):
"""Generic list response with metadata."""
items: list[T]
total: int
model_config = ConfigDict(from_attributes=True)
# Usage:
# ListResponse[ItemResponse]
When using fastapi-pagination, you don't need custom list schemas. The library provides Page[T]:
from fastapi_pagination import Page
# Router returns:
# Page[ItemResponse]
# Which produces:
# {
# "items": [...],
# "total": 100,
# "page": 1,
# "size": 50,
# "pages": 2
# }
from pydantic import computed_field
class ItemResponse(BaseResponseSchema):
name: str
price: float
quantity: int
@computed_field
@property
def total_value(self) -> float:
"""Computed field for total value."""
return self.price * self.quantity
from pydantic import Field
class ItemResponse(BaseResponseSchema):
internal_id: str = Field(serialization_alias="id")
item_name: str = Field(serialization_alias="name")
class UserResponse(BaseResponseSchema):
username: str
email: str
password_hash: str = Field(exclude=True) # Never serialized
from pydantic import BaseModel, Field
class ItemQueryParams(BaseModel):
"""Query parameters for listing items."""
search: str | None = Field(default=None, min_length=1, max_length=100)
category_id: UUID | None = None
min_price: float | None = Field(default=None, ge=0)
max_price: float | None = Field(default=None, ge=0)
is_active: bool = True
model_config = ConfigDict(extra="forbid") # Reject unknown params