AGENT SKILL

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

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: DateTimeField stores UTC; display converts to America/Fortaleza.
  • Constraints in the DB: prefer CheckConstraint/UniqueConstraint in Meta; reach for Python validators only when the rule needs relations or runtime data.
  • save() deriving fields: real pattern in apps/core/models/dat_registro.py — save() calls _calcular_nr_codigos() to compute nr_codigos from projeto_geral.
  • Default masks required: a model field with default= makes ModelSerializer accept a payload that omits it. When the field must be supplied, declare it as ChoiceField(required=True) on the write serializer (case Projeto.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 by self.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 overrides get_permissions(), the action decorator's classes are ignored. Check it before assuming an action's permissions. (SolicitacaoViewSet does this, mapping approve/ batch_approve to the Policy CanAccessSolicitationApprovals.)

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 → TestManualApproval for PA-01, TestPermissions for 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: ...=false header 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; serializers serializers/solicitacao.py, serializers/usuario.py; view views_solicitacao.py; permissions apps/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-derives nr_codigos).
  • PlanoFormacoes: models models/plano_formacoes.py, formacao.py, acompanhamento.py, prova.py; recalcular_ch() + taxa_realizacao property.
  • 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-domain skill (CP, RD, PA, RF, DAT, PlanoFormacoes)
  • RBAC: v2/docs/RBAC_NAMING.md + v2/docs/specs/backend/rbac.spec.md
  • Performance: performance-optimization skill
  • Imports: v2/docs/specs/backend/imports.spec.md (legacy ETL removed — use import_export_contract + DRF endpoints)

04 同仓库更多 Skills

matheusnorjosa
matheusnorjosa/aprender_sistema

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.

内容创作者写作与文案
★ 0
matheusnorjosa
matheusnorjosa/aprender_sistema

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.

★ 0
matheusnorjosa
matheusnorjosa/aprender_sistema

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.

测试与质量
★ 0
matheusnorjosa
matheusnorjosa/aprender_sistema

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.

★ 0
matheusnorjosa
matheusnorjosa/aprender_sistema

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.

★ 0
matheusnorjosa
matheusnorjosa/aprender_sistema

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).

人力资源
★ 0