OpenAPI Generation
The OpenAPI spec is generated by drf-spectacular from the views and their Pydantic schemas, and nobody edits it
by hand. What the generator cannot infer, the view states in @extend_schema.
@extend_schema
Section titled “@extend_schema”Every ViewSet action is decorated, with summary, description, parameters and responses.
Tag Convention
Section titled “Tag Convention”Use simple resource names as tags. A module only names its tags; grouping them by module happens when the published specs are generated (Configuration).
Admin tags: plain resource name (admin is the default audience):
Products # not "PIM Admin: Products"CategoriesFAQ GroupsDelivery PointsPublic tags: prefix with Public to distinguish from admin:
Public Delivery Points # not "Delivery Points" (that's admin)Public Delivery Point TypesPublic FAQApply via @extend_schema_view on the ViewSet class:
from drf_spectacular.utils import extend_schema, extend_schema_view
# Admin ViewSet@extend_schema_view( list=extend_schema(tags=["Products"]), retrieve=extend_schema(tags=["Products"]),)class ProductViewSet(viewsets.ViewSet): ...
# Public ViewSet@extend_schema_view( list=extend_schema(tags=["Public Delivery Points"]), retrieve=extend_schema(tags=["Public Delivery Points"]),)class PublicPointViewSet(viewsets.ViewSet): ...Operation Naming & Spec Quality
Section titled “Operation Naming & Spec Quality”Summary Field
Section titled “Summary Field”The summary in @extend_schema is the page title and sidebar label in the published docs. Every action has
one, written for a person.
Naming convention:
- List: “List {resources}” (e.g. “List products”)
- Retrieve: “Retrieve {resource} by {identifier}” (e.g. “Retrieve product by SKU”)
- Create/Update/Delete: “{Verb} {resource}”
- Custom actions: descriptive verb phrase (e.g. “List features in set”)
Operation IDs
Section titled “Operation IDs”Do NOT set operation_id manually. Auto-generated IDs are predictable and consistent. A list endpoint gets its
_list id when it is a ViewSet list action with a response schema: the item model when the view sets
pagination_class (the paginator documents the envelope), an explicit list model otherwise.
Post-Schema Checklist
Section titled “Post-Schema Checklist”After any ViewSet change:
make schema: regenerate the spec- Check Swagger UI (
/api/schema/swagger-ui/): no_2suffixes, all operations have clean summaries - The docs portal build must pass with the regenerated spec
Parameters and Responses
Section titled “Parameters and Responses”from drf_spectacular.utils import extend_schema, OpenApiParameter
class ProductViewSet(viewsets.ViewSet): @extend_schema( summary="List products", description="Returns paginated product catalog for the given channel.", parameters=[ OpenApiParameter(name="channel_idx", location="path", description="Channel identifier"), OpenApiParameter(name="search", description="Search by SKU or name"), ], responses={200: ProductListResponse}, ) def list(self, request, *args, **kwargs): ...OpenAPI Schema Management
Section titled “OpenAPI Schema Management”In the service:
make schema # uv run python manage.py spectacular --file schema.yamluv run python manage.py spectacular --validate --fail-on-warn # validateA module runs the same validation as a test (pattern: tests/test_package.py of entirius-django-siteintel):
def test_openapi_schema_validates(tmp_path): call_command("spectacular", "--validate", "--fail-on-warn", "--file", str(tmp_path / "schema.yaml"))The service serves the spec (main/urls.py); the host is http://localhost:8000 under make run, :8100 in the
harness:
| URL | What |
|---|---|
/api/schema/swagger-ui/ | Swagger UI |
/api/schema/redoc/ | Redoc |
/api/schema/ | raw schema |
The three routes are staff-only by default (API_SCHEMA_PUBLIC = False in the service settings); the harness
opens them.
drf-spectacular Configuration
Section titled “drf-spectacular Configuration”In the service settings (main/settings.py):
SPECTACULAR_SETTINGS = { "TITLE": "Entirius Volkanos Service API", "DESCRIPTION": "Base Volkanos service of the Entirius platform", "VERSION": _PROJECT_VERSION, "SERVE_INCLUDE_SCHEMA": False, "OAS_VERSION": "3.1.0",}OAS_VERSION is 3.1.0 because modules describe their Pydantic schemas with examples (JSON Schema 2020-12), which
is only legal from OpenAPI 3.1 on; under the 3.0.3 default spectacular --validate fails on every module that
documents an example.
The published specs are generated by the harness: make schema in
entirius-zeno applies the audience split (admin and storefront), the
v2 filter and the tag groups with their descriptions. The service and the modules carry no hook for the split, the filter or the groups; a
module only names its tags.
Build a Module: the standard applied to one module, from an empty folder to a green schema validation