Manuals — Views¶
Overview¶
The views layer exposes the manuals app through REST API endpoints.
It is responsible for:
- request parsing
- authentication and permission enforcement
- queryset construction
- serializer selection
- response construction
- light orchestration (calling services)
It is not responsible for:
- business logic
- nested content synchronization
- media cleanup workflows
- PDF rendering internals
Those responsibilities belong to the service layer.
View structure¶
The views are split into modules for clarity:
views/taxonomy.pyviews/manuals.pyviews/chapters.pyviews/callouts.pyviews/media.pyviews/downloads.py
This prevents one large monolithic views.py.
High-level flow¶
flowchart TD
Request --> Auth
Auth --> HasOrg
HasOrg --> View
View --> Serializer
Serializer --> Service
Service --> Serializer
Serializer --> Response
Shared behavior¶
Org scoping¶
All views use:
- IsAuthenticated
- HasCurrentOrg
Helper:
_org(request)extracts the active org
All querysets must be filtered by org through:
- manual
- chapter → manual
- section → chapter → manual
- step_group → chapter → manual
- step → step_group → chapter → manual
Parser configuration¶
Manual-related endpoints support:
- JSON
- multipart/form-data
- file uploads
Used parsers:
- JSONParser
- MultiPartParser
- FormParser
Taxonomy views¶
CategoryViewSet¶
Responsibilities:
- CRUD for categories
- org-scoped filtering
Key behavior:
- queryset filtered by current org
- org automatically assigned on create
TopicViewSet¶
Responsibilities:
- CRUD for topics
- org-scoped filtering
Key behavior:
- identical structure to CategoryViewSet
- includes color metadata
Manual views¶
ManualViewSet¶
Main entry point for manuals.
Responsibilities¶
- list manuals
- retrieve manual detail
- create/update manuals
- nested content handling via serializer + services
- filtering, search, ordering
- cover upload/remove
- PDF export
Query optimization¶
ManualViewSet dynamically adjusts queryset based on:
- action (list vs retrieve)
- embed query parameter
Embed parameter¶
Example:
?embed=chapters,items
Controls whether deep relationships are prefetched.
Query strategy¶
flowchart TD
Callout --> Manual
Callout --> Chapter
Callout --> Section
Callout --> StepGroup
Callout --> Step
Manual --> Org
Chapter --> Org
Section --> Org
StepGroup --> Org
Step --> Org
Ensures only callouts within the current org are accessible.
Media views¶
ManualMediaViewSet¶
Responsibilities:
- upload media
- list media
- delete media
- enforce org safety
- trigger cleanup
Create flow¶
flowchart TD
A[Upload request] --> B[Validate file]
B --> C[Validate parent shape]
C --> D[Check parent belongs to org]
D --> E[Create ManualMedia]
E --> F[Return serialized media]
¶
flowchart TD
A[Upload request] --> B[Validate file]
B --> C[Validate parent shape]
C --> D[Check parent belongs to org]
D --> E[Create ManualMedia]
E --> F[Return serialized media]Delete flow¶
flowchart TD
A[Delete media] --> B[Load media]
B --> C[Call cleanup_after_media_delete]
C --> D[Remove inline references]
D --> E[Return 204]
¶
flowchart TD
A[Delete media] --> B[Load media]
B --> C[Call cleanup_after_media_delete]
C --> D[Remove inline references]
D --> E[Return 204]Key responsibilities¶
- enforce parent ownership via service
- prevent cross-org attachment
- trigger section/step cleanup after deletion
Download views¶
ManualCoverDownloadView¶
Responsibilities:
- serve manual cover image
Behavior:
- validates org ownership
- supports:
- S3 signed redirect
- local file streaming
ManualMediaDownloadView
Responsibilities:
- serve media file
Behavior:
- validates org ownership
- supports:
- S3 redirect
- local streaming
⸻
Download flow
flowchart TD
Request --> ValidateOrg
ValidateOrg --> FindFile
FindFile -->|S3| Redirect
FindFile -->|Local| StreamFile
Filtering, search, ordering¶
Filtering¶
ManualViewSet supports:
- category
- topic
- is_public_external
Search¶
- title
- description
Ordering¶
- published_at
- title
- order
Permissions¶
All views use layered permissions:
- IsAuthenticated
- HasCurrentOrg
This ensures:
- user is authenticated
- org context is resolved
- data is scoped to org
Responsibilities by layer¶
Views own¶
- request parsing
- permission checks
- queryset filtering
- serializer selection
- response formatting
- light orchestration
Services own¶
- nested content synchronization
- chapter/item orchestration
- media cleanup
- PDF generation
Serializers own¶
- payload validation
- response shaping
Models own¶
- data integrity
- constraints
- relationships
Design principles¶
Thin views¶
Views should remain small and readable.
They should:
- delegate logic
- not implement workflows
Explicit endpoints¶
Custom actions are used for:
- cover management
- PDF export
- file downloads
This keeps API behavior explicit.
Org-first filtering¶
All data access is scoped to org.
No endpoint should expose cross-org data.
Query efficiency¶
Deep manual responses are optimized via:
- select_related
- prefetch_related
- conditional embedding
Best practices¶
- keep views thin and declarative
- always filter by org
- avoid embedding business logic in views
- use services for orchestration
- use serializers for validation only
- optimize queries when returning nested data
Future extensions¶
Possible improvements:
- dedicated public/manual endpoints for external access
- caching layer for manual detail responses
- async PDF generation for large manuals
- versioning support for manuals
- granular permissions (read vs edit vs publish)
- bulk media upload endpoints
Summary¶
The views layer exposes the manuals system through a clean REST interface.
It provides:
- taxonomy endpoints
- manual management
- chapter management
- callout management
- media upload and cleanup
- file downloads
- PDF export
It is designed to be:
- thin
- org-safe
- optimized for nested reads
- aligned with the service layer
The key idea:
views orchestrate requests and responses; services perform the actual work.