Adding a Feature
Add a feature to a generated Djass project by choosing one user outcome, mapping it to the repository's existing apps, and writing acceptance tests before widening the scope. The private-upload example below turns that process into a concrete build brief. It is work you implement, not an upload feature that Djass generates for you.
1) Start with one vertical slice
Define the smallest shippable slice that includes:
- domain logic,
- user/API surface,
- and success/failure states.
Avoid starting with broad refactors.
2) Place code in the right app
- Domain models/services →
apps/core - API routers/schemas →
apps/api - Product pages/templates →
apps/pages+frontend/templates - Async work →
apps/core/tasks.pyqueued through Django Q2
3) Implement in this order
- Model changes and migrations
- Service/business logic
- API/view layer
- Template/UI updates
- Background task wiring (if needed)
- Tests and regression checks
4) Keep operations safe
If the feature changes background processing or account-access flows:
- add explicit logs for traceability,
- persist failure reasons users can understand,
- keep retry paths available (manual or automated).
For incremental production release, separate authorization from rollout and write the rollback contract before enabling the new path. Use the Django feature-flags production guide for safe defaults, background-job admission, evidence, tests, and cleanup.
5) Ship with docs in the same PR
If behavior, architecture, or setup changed, update docs in the same PR.
At minimum, update:
- the relevant docs page,
- any setup instructions affected,
- and examples/commands users rely on.
Worked example: add a private attachment
Start with one job: a signed-in customer uploads one attachment, sees its processing status, and downloads it only after validation succeeds. Leave shared folders, public links, bulk uploads, and resumable transfers out of the first slice. Choose the permitted file types, maximum size, retention period, and validation service before implementation; those are product decisions, not defaults supplied by this example.
Check the generated baseline first
If you do not have a repository yet, follow the project-generation workflow and review the available options. Enable Use S3 only if you intend to use object storage. Generation requires the appropriate Djass access.
The bundled starter inspected on October 9, 2026 provides storage settings,
not an upload form, scanner, or private-download feature. Its S3 media baseline
uses public-read and unsigned URLs. Do not use that baseline unchanged for
private attachments. Choose a private bucket or prefix, remove the public
ACL, and verify anonymous reads are denied before accepting customer files.
The S3 access guide explains policy and signed-URL
configuration; changing URL signing alone does not make an object private.
Turn the outcome into a build brief
Give your coding agent the following task in the generated repository, not in the hosted Djass application. This is a proposed feature contract, not ready-to-run code:
Read this repository's agent instructions and existing account, storage, and background-job conventions. Build one owner-scoped attachment workflow. First report the chosen size/type limits and storage policy; flag any missing decision before accepting uploads. Persist an owner, a server-generated object key, and processing state. Keep unvalidated bytes private. Add an authenticated upload form, an owner-only status view, and a download endpoint that checks ownership and readiness on every request. Queue validation after the database commit and make retries idempotent. Define cleanup for rejected files and interrupted work. Show the tests and remaining deployment checks before calling the feature complete. Never put credentials or signed URLs in logs.
Keep the model and state transitions in apps/core; add the user-facing view
and template using the repository's existing page conventions. Use
apps/core/tasks.py for queued work. Add an API surface only if the first
customer workflow needs one. For the detailed state machine, finalization
rules, and failure cases, use the upload pipeline guide
rather than inventing a second implementation contract.
Prove the user outcome
Acceptance tests should demonstrate that:
- one valid upload creates one owned record and progresses to a downloadable state;
- another account cannot inspect its status or obtain its download;
- an anonymous request to the stored object is denied;
- a disallowed file or failed validation never becomes downloadable;
- a retried task does not create duplicate accepted files;
- interrupted processing and deletion can be reconciled safely.
Use the Django 6.0 file-upload reference for form binding and upload-handler behavior, and the OWASP file-upload checklist for defense-in-depth controls. Run provider and proxy checks separately from unit tests: a mocked storage backend cannot prove the production access policy or request-size limit. This brief does not certify an implementation as secure.
Definition of done
A feature is done when:
- users can complete the intended job,
- unhappy paths are handled,
- docs are updated,
- and runtime/config impact is understood.