The view mixin

Just as with our serializers, our API views require a mixin to support the extensions - the SerializerExtensionsAPIViewMixin class. Your views will now look something like:

from rest_framework.generics import RetrieveAPIView
from rest_framework_serializer_extensions.views import SerializerExtensionsAPIViewMixin

from app import models


class RetriveOwnerAPIView(SerializerExtensionsAPIViewMixin, RetrieveAPIView):
    queryset = models.Owner.objects.all()
    serializer_class = OwnerSerializer
    ...

By adding the mixin, all of the serializer extensions are now supported. Your end users can now control exactly what is serialized through query parameters:

>>> GET /owner/1/?expand=cars__model&exclude=name
{
  "id": 1,
  "organization_id": 1,
  "cars": [
    {
      "id": 1,
      "variant": "P100D",
      "model": {
        "id": 1,
        "name": "Model S"
      }
    }
  ]
}

View-based context

The above example works on a per-request basis, but you can set up your view to control the serializer context too:

# Using fixed attributes
class FixedAPIView(SerializerExtensionsAPIViewMixin, RetrieveAPIView):
    queryset = models.Owner.objects.all()
    serializer_class = OwnerSerializer
    extensions_expand = {'organization'}
    extensions_expand_id_only = {'cars'}
    extensions_exclude = set()
    extensions_only = set()


# Or calculated
class DynamicAPIView(SerializerExtensionsAPIViewMixin, RetrieveAPIView):
    queryset = models.Owner.objects.all()
    serializer_class = OwnerSerializer

    def get_extensions_mixin_context(self):
        context = super(DynamicAPIView, self).get_extensions_mixin_context()
        context['expand'] = set([
            field_name for field_name in context['expand']
            if field_name != 'prevent_expansion'
        ])
        return context

Whilst the view sets the defaults, the extension context can be overriden by the end using through query parameters.

Disabling query parameter modification

You can disable users from modifying the serialized result:

# Using a fixed attribute
class FixedAPIView(SerializerExtensionsAPIViewMixin, RetrieveAPIView):
    extensions_query_params_enabled = False


# Or depending on the request context
class PossiblyFixedAPIView(SerializerExtensionsAPIViewMixin, RetrieveAPIView):
    def get_extensions_query_params_enabled(self):
        return random.choice([True, False])

Alternatively, you can also disable the feature globally through the QUERY_PARAMS_ENABLED setting:

# settings.py
REST_FRAMEWORK = dict(
    SERIALIZER_EXTENSIONS=dict(
        QUERY_PARAMS_ENABLED=False
    )
)