Projections — Aquilia Documentation
Comprehensive guide and documentation for Projections in the Aquilia framework. View API reference, examples, and implementation patterns.
Contracts / Projections Projections Projections let you define named subsets of fields within a single Contract. Instead of creating separate Contracts for list views vs detail views vs admin views, you declare projections and select them at render time. Why Projections? , , , , ].map((item, i) => ( ))} Defining Projections Projections are declared in the Spec inner class as a dictionary mapping names to field lists. from aquilia.contracts import Contract, TextFacet, EmailFacet, FloatFacet, Computed, Lens class ProductContract(Contract): name = TextFacet(max_length=200) slug = TextFacet(max_length=100) price = FloatFacet() description = TextFacet(max_length=5000) internal_notes = TextFacet(max_length=2000) category = TextFacet() sku = TextFacet() stock_count = IntFacet() is_active = BoolFacet() created_at = DateTimeFacet(read_only=True) reviews = Lens("ReviewContract", many=True) # Computed field display_price = Computed(lambda inst: "$%.2f" % inst.price) class Spec: model = Product fields = "__all__" read_only_fields = ["id", "created_at"] # Projection definitions projections = # Default projection when none specified default_projection = "summary" Special Projection Names Name Meaning , , , , ].map((row, i) => ( ))} Using Projections product = await Product.objects.get(id=1) # Use default projection ("summary") data = ProductContract(instance=product).data # # Use minimal projection data = ProductContract(instance=product, projection="__minimal__").data # # Use detail projection (excludes internal_notes, stock_count) data = ProductContract(instance=product, projection="detail").data # Use admin projection (all fields) data = ProductContract(instance=product, projection="__all__").data # Serialize many instances with projection products = await Product.objects.all() data = ProductContract(instance=products, many=True, projection="__minimal__").data Projections in Controllers from aquilia import Controller, Get class ProductController(Controller): prefix = "/api/products" @Get("/") async def list_products(self, ctx): products = await Product.objects.all() # Minimal projection for list views — fast, small payload return ctx.json( ProductContract(instance=products, many=True, projection="__minimal__").data ) @Get("/ ") async def detail(self, ctx, id: int): product = await Product.objects.get(id=id) # Full detail projection return ctx.json( ProductContract(instance=product, projection="detail").data ) @Get("/ /admin") async def admin_detail(self, ctx, id: int): product = await Product.objects.get(id=id) # Admin sees everything return ctx.json( ProductContract(instance=product, projection="__all__").data ) Subscript Syntax for Lenses When using Lens facets, you can select which projection the nested Contract uses via Python's subscript syntax: from aquilia.contracts import Contract, Lens class OrderContract(Contract): # Render products with their "summary" projection items = Lens(ProductContract["summary"], many=True) # Render customer with "public" projection customer = Lens(CustomerContract["public"]) class Spec: model = Order fields = "__all__" # This is shorthand for: # items = Lens(ProductContract, many=True, projection="summary") ProjectionRegistry API # Inspect available projections print(ProductContract._projections.available) # ["__minimal__", "summary", "detail", "__all__", "public"] # Get default projection name print(ProductContract._projections.default_name) # "summary" # Resolve a projection to field names fields = ProductContract._projections.resolve("__minimal__") # ["id", "name", "price", "slug"] # Resolve exclusion projection fields = ProductContract._projections.resolve("detail") # All fields except "internal_notes" and "stock_count" )
Go to Homepage