一键导入
advanced-alchemy
Expert knowledge for Advanced Alchemy / SQLAlchemy ORM patterns. Use when working with models, services, repositories, or database migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Expert knowledge for Advanced Alchemy / SQLAlchemy ORM patterns. Use when working with models, services, repositories, or database migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Expert knowledge for Litestar Python web framework. Use when working with Litestar routes, plugins, middleware, dependency injection, or configuration.
Use when running installs, dev servers, tests, lint/format, codegen, or Docker lifecycle tasks; Taskfile is the source of truth.
Use when creating or updating Celery tasks, async job logic, or Beat schedules in the backend.
Use when changing GraphQL schema, resolvers, or frontend GraphQL documents so the contract and codegen stay in sync.
Use for change discipline, validation expectations, and safety checks when making repo changes.
| name | advanced-alchemy |
| description | Expert knowledge for Advanced Alchemy / SQLAlchemy ORM patterns. Use when working with models, services, repositories, or database migrations. |
from advanced_alchemy.base import UUIDAuditBase
from sqlalchemy import String, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
class User(UUIDAuditBase):
"""User model with audit fields (id, created_at, updated_at)."""
__tablename__ = "user_account"
__table_args__ = {"comment": "User accounts"}
__pii_columns__ = {"name", "email"} # PII tracking
# Required field
email: Mapped[str] = mapped_column(unique=True, index=True, nullable=False)
# Optional field with T | None
name: Mapped[str | None] = mapped_column(nullable=True, default=None)
# String with max length
username: Mapped[str | None] = mapped_column(
String(length=30), unique=True, index=True, nullable=True
)
# Boolean with default
is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
# Integer with default
login_count: Mapped[int] = mapped_column(default=0)
# Foreign key relationship
team_id: Mapped[UUID | None] = mapped_column(
ForeignKey("team.id", ondelete="CASCADE"),
nullable=True,
)
# Relationships
team: Mapped["Team"] = relationship(back_populates="members", lazy="selectin")
roles: Mapped[list["UserRole"]] = relationship(
back_populates="user",
lazy="selectin",
cascade="all, delete",
)
from litestar.plugins.sqlalchemy import repository, service
from app.db import models as m
class UserService(service.SQLAlchemyAsyncRepositoryService[m.User]):
"""Service for user operations."""
class Repo(repository.SQLAlchemyAsyncRepository[m.User]):
"""User repository."""
model_type = m.User
repository_type = Repo
match_fields = ["email"] # For upsert matching
# Transform data before create
async def to_model_on_create(self, data: service.ModelDictT[m.User]) -> service.ModelDictT[m.User]:
return await self._populate_model(data)
# Transform data before update
async def to_model_on_update(self, data: service.ModelDictT[m.User]) -> service.ModelDictT[m.User]:
return await self._populate_model(data)
async def _populate_model(self, data: dict) -> dict:
"""Custom model population logic."""
if "password" in data:
data["hashed_password"] = await hash_password(data.pop("password"))
return data
# Custom service methods
async def get_by_email(self, email: str) -> m.User | None:
"""Get user by email."""
return await self.get_one_or_none(email=email)
async def authenticate(self, email: str, password: str) -> m.User:
"""Authenticate user."""
user = await self.get_by_email(email)
if not user or not verify_password(password, user.hashed_password):
raise PermissionDeniedException("Invalid credentials")
return user
# Create
user = await service.create({"email": "test@example.com", "name": "Test"})
# Get by ID
user = await service.get(user_id) # Raises NotFoundError if not found
user = await service.get_one_or_none(id=user_id) # Returns None
# Get by field
user = await service.get_one_or_none(email="test@example.com")
# List
users = await service.list()
# List with pagination
users = await service.list(limit_offset=(20, 0))
# List and count
users, count = await service.list_and_count()
# Update
user = await service.update(user_id, {"name": "New Name"})
# Upsert (create or update based on match_fields)
user = await service.upsert({"email": "test@example.com", "name": "Test"})
# Delete
await service.delete(user_id)
# Exists
exists = await service.exists(email="test@example.com")
# Count
count = await service.count()
from advanced_alchemy.filters import (
LimitOffset,
OrderBy,
SearchFilter,
CollectionFilter,
)
# Using filters
users = await service.list(
LimitOffset(limit=20, offset=0),
OrderBy(field_name="created_at", sort_order="desc"),
SearchFilter(field_name="name", value="John", ignore_case=True),
)
from advanced_alchemy.service.pagination import OffsetPagination
@get()
async def list_paginated(
self,
service: UserService,
limit: int = 20,
offset: int = 0,
) -> OffsetPagination[UserSchema]:
return await service.list_and_count(limit_offset=(limit, offset))
# Create migration
app database make-migrations
# Apply migrations
app database upgrade
# Downgrade
app database downgrade
from advanced_alchemy.exceptions import (
NotFoundError,
IntegrityError,
RepositoryError,
)
try:
user = await service.get(user_id)
except NotFoundError:
raise NotFoundException("User not found")
Mapped[] typing for all columnsT | None for optional fields (never Optional[T])UUIDAuditBase for auto id/created_at/updated_atRepo class pattern inside serviceslazy="selectin" for eager loadingmcp__context7__resolve-library-id(libraryName="advanced-alchemy", query="...")
mcp__context7__query-docs(libraryId="/litestar-org/advanced-alchemy", query="...")