mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-17 04:58:16 -06:00
Enable dynamic field inclusion for REST API serializers
This commit is contained in:
parent
f41105d5e3
commit
d99928435a
@ -12,6 +12,15 @@ __all__ = (
|
||||
class BaseModelSerializer(serializers.ModelSerializer):
|
||||
display = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def __init__(self, *args, requested_fields=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# If specific fields have been requested, omit the others
|
||||
if requested_fields:
|
||||
for field in list(self.fields.keys()):
|
||||
if field not in requested_fields:
|
||||
self.fields.pop(field)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_display(self, obj):
|
||||
return str(obj)
|
||||
|
@ -1,8 +1,11 @@
|
||||
import logging
|
||||
from functools import cached_property
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, PermissionDenied
|
||||
from django.db import transaction
|
||||
from django.db.models import ProtectedError, RestrictedError
|
||||
from django.db.models.fields.related import ManyToOneRel, RelatedField
|
||||
from django_pglocks import advisory_lock
|
||||
from netbox.constants import ADVISORY_LOCK_KEYS
|
||||
from rest_framework import mixins as drf_mixins
|
||||
@ -40,6 +43,40 @@ class BaseViewSet(GenericViewSet):
|
||||
if action := HTTP_ACTIONS[request.method]:
|
||||
self.queryset = self.queryset.restrict(request.user, action)
|
||||
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
|
||||
# Dynamically resolve prefetches for included serializer fields and attach them to the queryset
|
||||
serializer_class = self.get_serializer_class()
|
||||
model = serializer_class.Meta.model
|
||||
fields_to_include = self.requested_fields or serializer_class.Meta.fields
|
||||
prefetch = []
|
||||
for field_name in fields_to_include:
|
||||
try:
|
||||
field = model._meta.get_field(field_name)
|
||||
except FieldDoesNotExist:
|
||||
continue
|
||||
if isinstance(field, (RelatedField, ManyToOneRel, GenericForeignKey)):
|
||||
# TODO: Use serializer field source if set, else use its name
|
||||
prefetch.append(field_name)
|
||||
if prefetch:
|
||||
qs = qs.prefetch_related(*prefetch)
|
||||
|
||||
return qs
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
# If specific fields have been requested, pass them to the serializer
|
||||
if self.requested_fields:
|
||||
kwargs['requested_fields'] = self.requested_fields
|
||||
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
@cached_property
|
||||
def requested_fields(self):
|
||||
requested_fields = self.request.query_params.get('include')
|
||||
return requested_fields.split(',') if requested_fields else []
|
||||
|
||||
|
||||
class NetBoxReadOnlyModelViewSet(
|
||||
mixins.BriefModeMixin,
|
||||
|
Loading…
Reference in New Issue
Block a user