Mixins¶
The core.mixins layer provides reusable DRF-oriented building blocks for viewsets.
These mixins are designed to reduce duplication and enforce common backend conventions, especially around:
- organization scoping
- audit fields
- create/update behavior
They are infrastructure helpers, not business logic containers.
Purpose¶
Mixins exist to:
- standardize repeated DRF patterns
- keep viewsets small and consistent
- reduce boilerplate in feature apps
- enforce safe defaults
They are especially useful when many apps share the same structural needs.
Current Mixins¶
The current mixin layer includes:
OrgScopedViewSetMixinAuditFieldsViewSetMixin
OrgScopedViewSetMixin¶
This mixin ensures that a viewset is automatically scoped to the current organization.
Responsibilities¶
- filter queryset by
request.org - attach
orgautomatically on create
Behavior¶
Queryset scoping¶
If request.org exists:
- the queryset is filtered by the configured org field
If request.org does not exist:
- an empty queryset is returned
This prevents accidental cross-org access.
Create behavior¶
On create:
- the mixin injects the current org into
serializer.save(...)
If org is missing:
- it raises
PermissionDenied
Default org field¶
By default, the mixin assumes the model field is:
org
This can be customized using:
org_field = "your_custom_field"
Typical usage¶
Use this mixin when:
- the model is org-scoped
- the endpoint should always operate within the current org
- the org should never come from client input
AuditFieldsViewSetMixin¶
This mixin automatically sets audit fields on create and update.
Responsibilities¶
- set
created_byon create if supported by model - set
updated_byon create and update if supported by model
Behavior¶
On create:
- if model has
created_by, it is set torequest.user - if model has
updated_by, it is also set torequest.user
On update:
- if model has
updated_by, it is set torequest.user
Model detection¶
The mixin checks whether the serializer’s model contains the expected audit fields.
This allows the mixin to work safely across different models without requiring explicit configuration.
Why These Mixins Exist¶
Without mixins, many viewsets would repeat the same logic:
- filter by org
- inject org on create
- set created_by / updated_by
- handle missing org state
The mixins centralize those patterns and make behavior more predictable.
Relationship to Other Layers¶
Permissions¶
Mixins assume the request has already passed permission checks such as:
HasCurrentOrg
They do not replace permission enforcement.
Services¶
Mixins do not implement business logic.
They only help with common DRF viewset behavior.
All domain rules should still live in services.
Usage Example¶
A typical org-scoped audited viewset might combine both mixins:
OrgScopedViewSetMixinAuditFieldsViewSetMixin
This gives:
- automatic org filtering
- automatic audit field population
without repeating the same code in every app.
Execution Flow¶
flowchart TD
A[Request enters viewset] --> B[Permissions validate request.org]
B --> C[OrgScopedViewSetMixin filters queryset]
C --> D[Serializer validated]
D --> E[AuditFieldsViewSetMixin injects audit user]
E --> F[Object saved]
¶
flowchart TD
A[Request enters viewset] --> B[Permissions validate request.org]
B --> C[OrgScopedViewSetMixin filters queryset]
C --> D[Serializer validated]
D --> E[AuditFieldsViewSetMixin injects audit user]
E --> F[Object saved]
What Mixins Should NOT Do¶
Mixins should not:
- perform business authorization checks
- contain domain rules
- write audit logs
- replace service-layer validation
- parse request headers
- implement feature-specific behavior
Best Practices¶
Use OrgScopedViewSetMixin when:¶
- model is org-scoped
- current org must be enforced automatically
- org should never be provided by the client
Use AuditFieldsViewSetMixin when:¶
- model includes created_by and/or updated_by
- request user should be attached automatically
Combine them when appropriate¶
Many internal CRUD viewsets will benefit from using both.
Common Mistakes¶
Putting business logic in mixins¶
Mixins should stay generic and reusable.
Using mixins without proper permissions¶
If HasCurrentOrg is missing, org scoping may fail or return empty querysets.
Relying on mixins instead of services¶
Mixins help with DRF mechanics, not domain workflows.
Testing Strategy¶
Mixins are tested directly in the core test suite.
Tests verify:
- queryset scoping by org
- create behavior with and without org
- created_by / updated_by assignment
- no-op behavior when audit fields are absent
Benefits¶
The mixin layer provides:
- less boilerplate
- safer defaults
- more consistent CRUD behavior
- easier maintenance across apps
Summary¶
The core.mixins layer provides reusable DRF helpers for:
- org scoping
- audit field assignment
These mixins help keep viewsets clean while preserving the architecture principle that business logic belongs in services.