HTTP ViewSets & Routing
Fapix features **DRF-style `ModelViewSet` classes**, dynamic `DefaultRouter`, fine-grained permissions, and `@action` decorators.
---
## 1. Defining Models & ViewSets
### `apps/product/models.py`
```python
from tortoise import fields
from tortoise.models import Model
class Product(Model):
id = fields.UUIDField(pk=True)
name = fields.CharField(max_length=100)
slug = fields.CharField(max_length=100, unique=True)
description = fields.TextField(null=True)
price = fields.DecimalField(max_digits=10, decimal_places=2)
stock = fields.IntField(default=0)
is_active = fields.BooleanField(default=True)
created_at = fields.DatetimeField(auto_now_add=True)
class Meta:
table = "products"
apps/product/views.py
from fapix.views import ModelViewSet
from apps.auth.permissions import IsSuperUser, IsSuperUserOrRole
from .models import Product
from .schemas import (
ProductSchema,
ProductCreateSchema,
ProductUpdateSchema,
ProductRetrieveSchema,
)
class ProductViewSet(ModelViewSet):
model = Product
schema = ProductSchema # Default response schema
# Dynamic action schemas
action_schemas = {
"create": ProductCreateSchema,
"update": ProductUpdateSchema,
"retrieve": ProductRetrieveSchema,
"bulk_create": ProductCreateSchema,
}
lookup_fields = ["slug"]
# Action-level permissions
permission_classes = [] # Public read access
action_permissions = {
"create": [IsSuperUserOrRole("admin")],
"update": [IsSuperUser],
"destroy": [IsSuperUser],
"bulk_create": [IsSuperUser],
"bulk_delete": [IsSuperUser],
}
# Filtering, Searching, & Ordering
search_fields = ["name", "description"]
filterset_fields = ["is_active", "stock"]
ordering_fields = ["price", "id", "stock"]
default_ordering = ["-price"]
2. Function-Based Views & Decorators
from fastapi import FastAPI, Depends
from fapix.decorators import permission_classes, api_view
from apps.auth.permissions import IsAuthenticated
# Decorator approach
@api_view
@permission_classes([IsAuthenticated])
async def home():
return {"message": "Welcome Home"}
# Dependency Injection approach
async def profile(current_user=Depends(IsAuthenticated())):
return {"user": current_user}
3. URL Registration & DefaultRouter
apps/product/urls.py
from fastapi import APIRouter
from fapix.core.router import register_urlpatterns
from fapix.router import DefaultRouter
from . import views
router = APIRouter(prefix="/products", tags=["products"])
# 1. Initialize DefaultRouter and register ViewSets
product_router = DefaultRouter()
product_router.register("", views.ProductViewSet, basename="product")
# 2. Define custom/manual endpoints
urlpatterns = []
# 3. Extend with generated ViewSet pattern definitions
urlpatterns.extend(product_router.generate_urlpatterns())
# 4. Attach pattern definitions onto router instance
register_urlpatterns(router, urlpatterns)