ViewSets¶
Base classes and mixins that add consistent response wrapping, exception handling, and routing conventions to DRF ViewSets.
Mixins¶
PublicIDLookupMixin¶
Configures a ViewSet to look up objects by public_id instead of the internal primary key, keeping internal IDs out of your URLs.
| Attribute | Value |
|---|---|
lookup_field |
public_id |
lookup_url_kwarg |
id |
Usage
class UserViewSet(PublicIDLookupMixin, ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
A detail request to /users/abc123/ resolves internally as:
Tip
Place PublicIDLookupMixin before the ViewSet in the MRO so its lookup_field takes precedence.
CommonMixin¶
CommonMixin is composed of three smaller mixins:
class CommonMixin(
SuccessResponseMixin, PrefetchCacheInvalidationViewMixin, RequestActorViewMixin
):
"""
Convenience helpers shared across ViewSets.
"""
| Component | Provides |
|---|---|
SuccessResponseMixin |
Automatic success envelope wrapping |
RequestActorViewMixin |
The actor property (request.user), as previously documented under CommonMixin |
PrefetchCacheInvalidationViewMixin |
_invalidate_prefetched_cache(), new — see below |
_response(data=None, status_code=200, **kwargs)¶
A thin wrapper around rest_framework.response.Response with a default 200 status.
| Parameter | Type | Default | Description |
|---|---|---|---|
data |
any |
None |
Response payload |
status_code |
int |
HTTP_200_OK |
HTTP status code |
**kwargs |
Forwarded to Response |
RequestActorViewMixin¶
Adds convenience properties for accessing the requesting user and their profile.
actor¶
A cached property returning the authenticated request.user, or None if there is no request, no user, or the user isn't authenticated.
!!! note This differs from the plain self.request.user lookup previously described under CommonMixin: an anonymous request now resolves to None rather than Django's AnonymousUser instance. Code that branches on self.actor truthiness is unaffected, but code that expects an AnonymousUser object specifically should be updated.
actor_profile¶
A cached property returning actor.related_profile, or None if there is no actor (unauthenticated) or the attribute doesn't exist.
def get_queryset(self):
if self.actor_profile:
return Order.objects.filter(profile=self.actor_profile)
return Order.objects.none()
!!! tip Both properties are @cached_property, so they're computed once per request/view instance — safe to access repeatedly across perform_* and get_* hooks without re-hitting related_profile.
PrefetchCacheInvalidationViewMixin¶
Adds a helper for clearing a Django instance's cached prefetch_related()
results.
| Parameter | Type | Description |
|---|---|---|
instance |
model | Instance whose _prefetched_objects_cache should be cleared |
When a queryset has had prefetch_related() applied, Django caches the
related results on instance._prefetched_objects_cache. If the instance is
then mutated directly (e.g. a related object is added, removed, or changed)
without going through that cache, later related-object lookups on the same
instance return the stale, pre-mutation results. Calling
_invalidate_prefetched_cache(instance) clears that cache so the next
access re-queries the database.
SuccessResponseMixin¶
Intercepts finalize_response to wrap every successful response in the drf-corekit envelope, so action methods never need to wrap their own payloads.
Success envelope
Bypass condition
Responses with a status of 207 or ≥ 300 that already carry a structured error body are passed through unchanged:
Note
You do not need to call wrap_success_response yourself — any Response returned from your ViewSet is wrapped automatically.
ViewSets¶
All ViewSets below compose SuccessResponseMixin, and CommonMixin on top of the corresponding DRF base class.
ModelViewSet¶
A full CRUD ViewSet with response wrapping and exception mapping pre-applied.
Actions
| Method | Action |
|---|---|
GET /resource/ |
list |
POST /resource/ |
create |
GET /resource/<id>/ |
retrieve |
PUT /resource/<id>/ |
update |
PATCH /resource/<id>/ |
partial_update |
DELETE /resource/<id>/ |
destroy |
ReadOnlyModelViewSet¶
Exposes read-only endpoints only — no writes permitted.
Actions
| Method | Action |
|---|---|
GET /resource/ |
list |
GET /resource/<id>/ |
retrieve |
class CountryViewSet(ReadOnlyModelViewSet):
queryset = Country.objects.all()
serializer_class = CountrySerializer
ReadUpdateModelViewSet¶
Allows reading and updating records, but not creating or deleting them.
Actions
| Method | Action |
|---|---|
GET /resource/ |
list |
GET /resource/<id>/ |
retrieve |
PUT /resource/<id>/ |
update |
PATCH /resource/<id>/ |
partial_update |
class ProfileViewSet(ReadUpdateModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
NoUpdateModelViewSet¶
Allows create, and read, but no update or destroy.
Actions
| Method | Action |
|---|---|
POST /resource/ |
create |
GET /resource/ |
list |
GET /resource/<id>/ |
retrieve |
class CommentViewSet(NoUpdateModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
Note
Like ModelViewSet, ReadOnlyModelViewSet, and ReadUpdateModelViewSet,
both new ViewSets pick up SuccessResponseMixin,
and CommonMixin via _SharedMixin, so response wrapping and exception
mapping apply out of the box.
APIViewSet¶
A plain APIView with the drf-corekit conventions (response wrapping, exception mapping, actor) applied. Use this for non-model, action-oriented endpoints that don't need a router.