Code Generation¶
shakti generate (alias shakti g) scaffolds models and CRUD routers from a compact field DSL, so a full REST resource is a one-liner.
This writes both a model (app/models/post.py) and a CRUD router (app/routers/post.py), and registers the model import in app/models/__init__.py so Alembic picks it up.
kind options¶
shakti generate model Post title:str body:text # model only
shakti generate crud Post # router only (model must already exist)
shakti generate api Post title:str body:text # both
Field DSL¶
| Type | Python | SQLAlchemy column |
|---|---|---|
str (default if omitted) |
str |
String(255) |
text |
str |
Text |
int |
int |
Integer |
float |
float |
Float |
bool |
bool |
Boolean (defaults to False) |
datetime |
datetime |
DateTime(timezone=True) |
uuid |
str |
String(36), unique |
Modifiers (combine with more :): unique, nullable, index.
# generated app/models/user.py
class User(TimestampMixin, Base):
__tablename__ = "users"
email: Mapped[str] = Field(String(255), unique=True)
bio: Mapped[str | None] = Field(Text, nullable=True)
age: Mapped[int] = Field(Integer, index=True)
def __repr__(self) -> str:
return f"<User id={self.id}>"
Generated models include TimestampMixin (created_at/updated_at) by default.
Generated CRUD router¶
generate crud Post (or the CRUD half of generate api) produces a full Router at /posts using Repository:
router = Router(prefix="/posts")
@router.get("/") # list
@router.get("/{id:int}") # get_or_404
@router.post("/") # create
@router.put("/{id:int}") # update
@router.delete("/{id:int}") # delete
Wire it up like any other router:
After generating¶
Generated files are plain Python — nothing generated is regenerated in place, so edit freely once written. See Quick Start for this same flow end-to-end, and Migrations for what makemigrations/migrate actually do.