django-patterns
Django 5.2 + DRF implementation patterns specific to Aprender Sistema v2 (modular apps/core layout, HasPerm RBAC, read/write serializers, service layer, owner-scoped querysets). Use when writing a model, serializer, view/viewset, service, permission, or test in the v2 backend.
- License 许可
- Apache-2.0
- 最近更新
- 2026-11-11
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- django-patterns
- description
- Django 5.2 + DRF implementation patterns specific to Aprender Sistema v2 (modular apps/core layout, HasPerm RBAC, read/write serializers, service layer, owner-scoped querysets). Use when writing a model, serializer, view/viewset, service, permission, or test in the v2 backend.
02 资源文件 4
- 参考文档reference/model-template.md3.6 KB
- 参考文档reference/serializer-template.md4.1 KB
- 参考文档reference/test-template.md4.6 KB
- 参考文档reference/viewset-template.md4.0 KB
03 SKILL.md 正文
Django/DRF Patterns — Aprender Sistema v2
Implementation patterns for the v2 backend. This file holds the AS-v2-specific deltas;
the full copy-paste scaffolds live in reference/ (see pointers below). For anything
generic to Django/DRF, follow the framework defaults — this skill only documents where
AS v2 diverges.
Backend layout (modular)
The only real apps are apps/core (39 models, serializers/, services/) and
apps/dev_tools (15 seed commands, disabled in prod). apps/core is split into Python
packages, each with an __init__.py that re-exports its public names:
apps/core/
├── models/ # by domain; __init__.py re-exports all models
├── serializers/ # by domain; __init__.py re-exports
├── views/ # compat re-export wrappers (e.g. views/solicitacao.py)
├── views_*.py # canonical view modules (views_solicitacao.py, views_availability.py, …)
├── views_gcal/ # GCal views
├── rbac/ # RBAC SSOT (HasPerm, helpers, matrix, policies)
└── services/ # business logic (availability_service.py, gcal/, …)
Re-export discipline: when you add a model/serializer, re-export it in the package's
__init__.py so existing imports keep working. Note apps/core/views/solicitacao.py is a
thin compat wrapper — the canonical ViewSet lives in apps/core/views_solicitacao.py.
Quick reference
| Task | Pattern | Pointer |
|---|---|---|
| Model | SSOT + constraints + indexes + re-export | reference/model-template.md |
| Serializer (read) | StringRelatedField, formatted fields |
reference/serializer-template.md |
| Serializer (write) | PrimaryKeyRelatedField + validation |
reference/serializer-template.md |
| ViewSet | thin controller, logic in services | reference/viewset-template.md |
| Permission | HasPerm("codename") |
RBAC section below |
| Owner/sector scope | filter in get_queryset() |
RBAC section below |
| Test | nested classes per requirement, behavior asserts | reference/test-template.md |
| Query perf | select_related / prefetch_related |
Performance section below |
Models
Full scaffold: reference/model-template.md.
AS-v2 deltas to keep in mind:
- Timezone:
DateTimeFieldstores UTC; display converts toAmerica/Fortaleza. - Constraints in the DB: prefer
CheckConstraint/UniqueConstraintinMeta; reach for Python validators only when the rule needs relations or runtime data. save()deriving fields: real pattern inapps/core/models/dat_registro.py—save()calls_calcular_nr_codigos()to computenr_codigosfromprojeto_geral.- Default masks required: a model field with
default=makesModelSerializeraccept a payload that omits it. When the field must be supplied, declare it asChoiceField(required=True)on the write serializer (caseProjeto.fluxo, #1312).
Serializers (DRF)
Full scaffold + gotchas: reference/serializer-template.md.
Read/write split is the house style: read serializers are user-friendly
(StringRelatedField, formatted fields, nested), write serializers take IDs
(PrimaryKeyRelatedField) and validate. Pick per request in the ViewSet's
get_serializer_class().
Views / ViewSets
Full scaffold: reference/viewset-template.md.
AS-v2 deltas:
- Thin controllers: views validate + delegate to
apps/core/services/; keep business logic out of the view body. get_serializer_class()switches read vs write byself.action.- Owner/sector scope is filtered in
get_queryset()(see RBAC below), not re-checked in the body. get_permissions()override hides@action(permission_classes=...)— if a ViewSet overridesget_permissions(), the action decorator's classes are ignored. Check it before assuming an action's permissions. (SolicitacaoViewSetdoes this, mappingapprove/batch_approveto the PolicyCanAccessSolicitationApprovals.)
Permissions (RBAC)
The AS v2 RBAC is capability-based. SSOT is apps.core.rbac (DRF permissions, helpers,
data-scope constants, matrix, policies). NEVER use user.groups.filter(name=...) in
views/permissions — it is banned by scripts/rbac_lint.py (CI job [required] backend rbac-lint). apps/core/permissions.py is a compat shim — import from apps.core.rbac.
Canonical idiom — capability codenames are English (approve_solicitation,
create_solicitation, import_spreadsheet, operate_preagenda, …):
from apps.core.rbac import HasPerm
permission_classes = [HasPerm("create_solicitation")] # single capability
permission_classes = [HasPerm("operate_preagenda") | HasPerm("create_solicitation")] # OR
permission_classes = [IsAuthenticated, HasPerm("import_spreadsheet")] # AND
permission_classes = [~HasPerm("bloqueado")] # NOT
Aprovar não se gateia por HasPerm("approve_solicitation"): a decisão é a Policy
CanAccessSolicitationApprovals (regra única solicitation_approval_basis, 3 bases:
superuser, GERENTE vigente na gerência Superintendência, ou a capacidade de aprovar vinda do
pacote do perfil da gerência — DAT/Controle). A base do GERENTE não é capacidade, então
HasPerm a negaria. Ver reference/viewset-template.md.
HasPerm("a") | HasPerm("b") composition is tactical (ok for ≤2 capabilities). For ≥3 caps,
a shared rule, or "who can see this and why" repeated across sites, promote it to a Policy
class in apps/core/rbac/policies.py (e.g. CanAccessSolicitationApprovals,
CanUseGcal).
Programmatic checks outside views (services, signals, commands):
from apps.core.rbac import user_has_any_perm, user_has_all_perms
if user_has_any_perm(user, "operate_preagenda", "create_solicitation"):
...
Data-scope / object-level: filter in get_queryset() + capabilities — don't reimplement
identity checks by group.
from apps.core.services.solicitacao_scope import scope_solicitacoes
def get_queryset(self):
base = Solicitacao.objects.select_related("usuario") # dono = `usuario`
# escopo SSOT: global (superuser/capacidades) + gestora (GERENTE vigente) + APOIO + próprias
return scope_solicitacoes(base, self.request.user)
Full naming convention: v2/docs/RBAC_NAMING.md + v2/docs/specs/backend/rbac.spec.md.
Testing
Full scaffold + conventions: reference/test-template.md.
AS-v2 deltas:
- Nested classes per requirement (
TestSolicitacaoApproval→TestManualApprovalfor PA-01,TestPermissionsfor PA-02); docstrings name the rule. - Test behavior, not implementation — assert status code / persisted state / audit log, never that a method was called.
- RBAC asserts the 403 status, not
"Setor" in response.data(that ties the test to the legacy org chart). - Determinism: atomic counter for unique CPF/email (not
abs(hash(str)) % N); never hardcode a date whose assertion depends on a not-yet-reached deadline. - Pyright header: a new test file needs the same
# pyright: ...=falseheader its neighbors carry, or CI breaks.
Real suites in apps/core/tests/: test_solicitacao_fluxo.py,
test_solicitacao_approval_concurrency.py, test_views_solicitacao_coverage.py,
test_solicitacao_serializer_meet_link.py.
Performance
Quick rule: select_related (FK/OneToOne) + prefetch_related (M2M/reverse FK) to kill N+1.
Endpoint-level caching exists (e.g. availability_check: keys at timeout=300 via the
cache_availability_check decorator; the monthly availability grid caches in
views_availability_monthly.py with a TTL+jitter). For slow endpoints, deep N+1, bundle, or
Core Web Vitals, use the performance-optimization skill (perf SSOT) — don't duplicate
guidance here.
solicitacoes = Solicitacao.objects.select_related("usuario") # avoids N+1
Real implementations to copy from
- CRUD: models
apps/core/models/solicitacao.py,usuario.py,organizacao.py; serializersserializers/solicitacao.py,serializers/usuario.py; viewviews_solicitacao.py; permissionsapps/core/rbac. - DAT module (4-step workflow Carta → Contato → Reunião → Entrega): models
models/dat_acao.py,dat_cadastro.py,dat_registro.py(save()auto-derivesnr_codigos). - PlanoFormacoes: models
models/plano_formacoes.py,formacao.py,acompanhamento.py,prova.py;recalcular_ch()+taxa_realizacaoproperty. - Service layer:
services/availability_service.py(RD-01..RD-08),services/gcal/sync.py+gcal/payload.py(RF05/RF06),services/solicitacao_approval.py(PA-01..PA-07). - Import: command
import_export_contract+services/export_contract_importer.py(dry-run by default).
Related
- Business rules:
aprender-domainskill (CP, RD, PA, RF, DAT, PlanoFormacoes) - RBAC:
v2/docs/RBAC_NAMING.md+v2/docs/specs/backend/rbac.spec.md - Performance:
performance-optimizationskill - Imports:
v2/docs/specs/backend/imports.spec.md(legacy ETL removed — useimport_export_contract+ DRF endpoints)
04 同仓库更多 Skills
writing-standards
Apply AS v2 technical-writing standards (clarity, brevity, active voice, Python/Django conventions). Use when writing a README, a docstring (PEP 257), a commit message, a PR description, an error message, or any technical doc.
verification-gate
Verify before claiming success. Use when about to say something works/is done, after implementing a feature, after a bugfix, or before pushing — run the proof command and confirm output first.
test-driven-development
Write the failing test before the implementation in AS v2 (pytest + Django/DRF). Use when implementing a feature or fixing a bug, before any production code is written.
subagent-development
Orquestra subagents no AS v2 — decompõe a tarefa em domínios independentes, paraleliza e revisa em 2 estágios. Use ao delegar exploração, implementação ou validação cross-arquivo para acelerar o trabalho e poupar o contexto principal.
security-scan
Automated security scanning for AS v2. Use before commits or when reviewing changes for vulnerabilities. Runs dependency audit (pip-audit, npm audit), secret detection (grep patterns), and code pattern scanning (SQL injection, XSS, eval, pickle, hardcoded secrets). Integrates with project hooks system.
resume-handoff
Resume work from a saved handoff document, validating its state against the current codebase before continuing. Use when resuming work from a saved handoff after a context clear or in a new session (path, session name, or GitHub issue).