API Routes Generator - User Guide¶
This guide shows you how to use the API Routes Generator effectively with practical examples and common patterns.
Customizing Generated Routes¶
You can control which endpoints are generated and customize their behavior:
Selective Endpoint Generation¶
from fastedgy.api_route_model import api_route_model
# Enable only list and get endpoints
@api_route_model(list=True, get=True, create=False, patch=False, delete=False)
class ReadOnlyProduct(Model):
name = fields.CharField(max_length=200)
price = fields.DecimalField(max_digits=10, decimal_places=2)
class Meta:
tablename = "readonly_products"
# Custom endpoint configuration
@api_route_model(
list=True,
get=True,
create={"status_code": 201, "summary": "Create a new product"},
patch={"summary": "Update product details"},
delete=False # Disable delete endpoint
)
class Product(Model):
name = fields.CharField(max_length=200)
description = fields.TextField()
price = fields.DecimalField(max_digits=10, decimal_places=2)
class Meta:
tablename = "products"
Built-in Features¶
Generated endpoints automatically integrate with FastEdgy's advanced features:
- Pagination - Standard limit/offset pagination with metadata
- Ordering - Sort by any field including nested relations
- Query Builder - Advanced filtering with X-Filter header
- Fields Selector - Control response fields with X-Fields header
# Example combining all features
GET /api/products/?limit=25&order_by=category.name,price:desc
X-Filter: ["&", [["is_active", "=", true], ["price", ">=", 100]]]
X-Fields: name,price,category.name,description
Working with Relationships¶
ForeignKey relationships¶
A foreign key points to a single related record. The same field accepts several input forms, including the same operations as collections applied to one record.
Simple mode¶
For the common cases, set the field to an id, an object or null:
# Link by id
POST /api/products/
{"name": "Smartphone", "category": 1, "price": "599.99"}
# Link by object (id only)
POST /api/products/
{"name": "Smartphone", "category": {"id": 1}, "price": "599.99"}
# Link and update the related record (id plus other properties)
POST /api/products/
{"name": "Smartphone", "category": {"id": 1, "name": "Phones"}, "price": "599.99"}
# Unlink (nullable foreign keys only)
PATCH /api/products/42
{"category": null}
Advanced mode¶
For the remaining cases, use a single operation [action, value] (the same actions as collections, applied to one record):
Available operations:
| Operation | Description | Example Value |
|---|---|---|
link | Link an existing record | ["link", 42] |
unlink | Remove the link (keep record) | ["unlink"] |
create | Create a new record and link it | ["create", {"name": "New"}] |
update | Update the record and link it | ["update", {"id": 10, "name": "Updated"}] |
delete | Delete the record and remove the link | ["delete", 15] |
When to use each form:
- id /
["link", id]- Link an existing record - object
{"id": ...}- Link an existing record (object form) - object
{"id": ..., ...}/["update", {...}]- Link a record and update its properties null/["unlink"]- Remove the link without deleting the record (nullable foreign keys only)["create", {...}]- Create a record and link it in a single request["delete", id]- Permanently delete the record and remove the link
Examples:
# Create a related record and link it in a single request
POST /api/products/
{"name": "Smartphone", "category": ["create", {"name": "Phones"}], "price": "599.99"}
# Update the linked record and ensure the link
PATCH /api/products/42
{"category": ["update", {"id": 1, "name": "Renamed"}]}
# Delete the linked record and clear the foreign key
PATCH /api/products/42
{"category": ["delete", 1]}
Required foreign keys
A required (non-nullable) foreign key cannot be unlinked: null and ["unlink"] are rejected.
Foreign keys can be filtered by related fields too:
GET /api/products/
X-Filter: ["category.name", "=", "Electronics"]
GET /api/products/
X-Filter: ["category", "=", 1]
ManyToMany & OneToMany relationships¶
FastEdgy provides two modes for managing collections of related records.
Simple mode¶
For small sets or complete replacements, use a simple list of IDs:
# Create with related items
POST /api/products/
{
"name": "Laptop",
"tags": [1, 2, 3]
}
# Replace all relations
PATCH /api/products/42
{
"tags": [4, 5, 6]
}
The simple mode automatically executes a set operation that replaces all existing relations.
Advanced mode¶
For large collections or partial updates, use granular operations to avoid performance issues:
Performance optimization
When a product has 1000 linked tags and you want to add just one more, simple mode would require sending 1001 IDs and the server would unlink 1000 relations then re-link 1001. Advanced mode lets you send just ["link", 1001] for optimal performance.
Available operations:
| Operation | Description | Example Value |
|---|---|---|
link | Add relation to existing record | ["link", 42] |
unlink | Remove relation (keep record) | ["unlink", 23] |
create | Create new record and link it | ["create", {"name": "New"}] |
update | Update record and ensure link | ["update", {"id": 10, "name": "Updated"}] |
delete | Delete record and remove relation | ["delete", 15] |
set | Replace all relations | ["set", [1, 2, 3]] |
clear | Remove all relations | ["clear"] |
When to use each operation:
link- Add one item to a large existing collection without touching othersunlink- Remove one item from a large collectionset- Reset the entire collection (same as simple mode)clear- Revoke all access or empty the collectioncreate- Create and link in a single operationupdate- Modify a linked record and ensure the link existsdelete- Permanently remove a linked record
Examples:
# Add one item to existing large collection
PATCH /api/products/42
{
"tags": [["link", 1001]]
}
# Multiple targeted modifications
PATCH /api/products/42
{
"tags": [
["link", 50],
["unlink", 23],
["update", {"id": 10, "name": "Updated Name"}]
]
}
# Create and link in one request
POST /api/products/
{
"name": "Gaming Laptop",
"tags": [
["link", 1],
["create", {"name": "Limited Edition"}]
]
}
# Complete reset (equivalent to simple mode)
PATCH /api/products/42
{
"tags": [["set", [1, 2, 3]]]
}
# Clear all relations
PATCH /api/products/42
{
"tags": [["clear"]]
}
Operation order:
Operations are executed sequentially in the order provided:
PATCH /api/products/42
{
"tags": [
["clear"], # 1. Remove all existing tags
["link", 1], # 2. Add tag 1
["link", 2], # 3. Add tag 2
["create", {"name": "New Tag"}] # 4. Create and add new tag
]
}
Error responses:
A well-formed operation that targets a missing record returns a 400 Bad Request:
A malformed operation (wrong shape or unknown action, e.g. ["link"] without a value) no longer matches the typed request schema and is rejected by request validation with a 422 Unprocessable Entity:
// 422 Unprocessable Entity - Invalid operation format
{
"detail": [
{
"type": "...",
"loc": ["body", "tags", 0],
"msg": "..."
}
]
}
Data Export¶
Every model gets automatic export functionality supporting CSV, XLSX, and ODS formats:
# Export with all features support
GET /api/products/export?format=csv&limit=1000
X-Filter: ["is_active", "=", true]
X-Fields: name,price,category.name
Error Handling¶
Generated endpoints provide consistent error responses:
- 400 Bad Request: Validation errors with field details
- 404 Not Found: Item not found
- 403 Forbidden: Insufficient permissions
- 422 Unprocessable Entity: Invalid request data
Admin Routes¶
Create separate admin endpoints with different permissions:
from fastedgy.api_route_model import admin_api_route_model
@admin_api_route_model() # Separate from regular routes
class AdminUser(Model):
username = fields.CharField(max_length=150)
is_staff = fields.BooleanField(default=False)
# Register on separate admin router
admin_router = APIRouter(prefix="/admin/api", dependencies=[Depends(admin_required)])
register_admin_api_route_models(admin_router)
Performance Optimization¶
Generated endpoints include automatic optimizations:
- Query Optimization: Automatic
select_related()for filtered/selected relations - Memory Management: Pagination prevents large dataset memory issues
- Data Transfer: Field selection reduces response size
Next Steps¶
Ready for more advanced customization? Check out:
- Advanced Usage - Custom actions and route customization
- View Transformers - Data transformation hooks