Auto CRUD Routes¶
PySpring Model can automatically generate RESTful CRUD endpoints for all your models. When enabled, every PySpringModel entity gets a full set of HTTP routes — no controllers or boilerplate required.
Enable auto CRUD routes¶
Set create_crud_routes to true in your application-properties.json:
{
"py_spring_model": {
"sqlalchemy_database_uri": "sqlite:///./app.db",
"create_all_tables": true,
"create_crud_routes": true
}
}
| Property | Type | Default | Description |
|---|---|---|---|
create_crud_routes |
bool |
false |
Automatically expose CRUD REST endpoints for all models |
That's it. No additional code is needed. When the application starts, PySpring registers routes for every model that extends PySpringModel with table=True.
How it works¶
- On startup,
PySpringModelStarterregisters aPySpringModelRestController. - The controller discovers all
PySpringModelsubclasses viaPySpringModel.get_model_lookup(). - For each model, it derives a resource name from the table name (the snake_case version of the class name) and registers CRUD routes under that name.
For example, given this model:
from py_spring_model import PySpringModel, Field
class UserProfile(PySpringModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str = Field()
email: str = Field()
age: int = Field()
The table name is user_profile (auto-converted from UserProfile), and the following endpoints are registered:
Generated endpoints¶
Get by ID¶
Retrieve a single record by its primary key.
Get all (paginated)¶
Retrieve a paginated list of records.
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "age": 30},
{"id": 2, "name": "Bob", "email": "bob@example.com", "age": 25}
]
Count¶
Get the total number of records.
Get multiple by IDs¶
Retrieve multiple records by a list of IDs.
Create¶
Create a new record.
POST /user_profile
Content-Type: application/json
{
"name": "Charlie",
"email": "charlie@example.com",
"age": 28
}
Batch create¶
Create multiple records at once.
POST /user_profile/batch
Content-Type: application/json
[
{"name": "Dave", "email": "dave@example.com", "age": 35},
{"name": "Eve", "email": "eve@example.com", "age": 22}
]
Update by ID¶
Update an existing record by its primary key. The request body should contain the full model data.
PUT /user_profile/1
Content-Type: application/json
{
"name": "Alice Updated",
"email": "alice@new.com",
"age": 31
}
Delete by ID¶
Delete a single record. Returns 204 No Content on success.
Batch delete¶
Delete multiple records by their IDs. Returns 204 No Content on success.
Endpoint summary¶
| Method | Path | Description |
|---|---|---|
GET |
/{resource}/count |
Count all records |
GET |
/{resource}/{id} |
Get one by ID |
GET |
/{resource}/{limit}/{offset} |
Get paginated list |
POST |
/{resource}/ids |
Get multiple by IDs |
POST |
/{resource} |
Create one |
POST |
/{resource}/batch |
Create multiple |
PUT |
/{resource}/{id} |
Update one by ID |
DELETE |
/{resource}/{id} |
Delete one by ID |
DELETE |
/{resource}/batch |
Delete multiple by IDs |
Resource naming¶
The resource name in the URL is derived from the model's table name, which is the snake_case conversion of the class name:
| Class name | Resource name (URL) |
|---|---|
User |
/user |
UserProfile |
/user_profile |
OrderItem |
/order_item |
ID type support¶
Auto CRUD routes support both int and UUID primary keys. The ID type is automatically detected from the model's id field annotation:
from uuid import UUID, uuid4
class Article(PySpringModel, table=True):
id: UUID = Field(default_factory=uuid4, primary_key=True)
title: str = Field()
Swagger UI¶
All generated routes include OpenAPI metadata (summary, description, and tags). When your application is running, you can explore the auto-generated endpoints in the interactive Swagger UI at:
Each model's endpoints are grouped under a tag matching the resource name, making it easy to browse and test.
Complete example¶
# models.py
from py_spring_model import PySpringModel, Field
class Product(PySpringModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str = Field()
price: float = Field()
category: str = Field()
class Order(PySpringModel, table=True):
id: int = Field(default=None, primary_key=True)
product_id: int = Field()
quantity: int = Field()
# main.py
from py_spring_core import PySpringApplication
from py_spring_model import PySpringModelStarter
def main():
app = PySpringApplication(
"./app-config.json",
starters=[PySpringModelStarter()],
)
app.run()
if __name__ == "__main__":
main()
// application-properties.json
{
"py_spring_model": {
"sqlalchemy_database_uri": "sqlite:///./shop.db",
"create_all_tables": true,
"create_crud_routes": true
}
}
With this setup, the application exposes full CRUD routes for both /product and /order automatically.
Tip
Auto CRUD routes work alongside custom CrudRepository classes and RestController classes. You can use auto-generated routes for quick prototyping and add custom repositories or controllers for more complex business logic.
Note
Auto CRUD routes use the same @Transactional session management as CrudRepository. Each request gets its own database session that is automatically cleaned up via the session middleware.