Advanced Topics

Customization

Parameter names and wildcard values can be configured with the Django setting REST_FLEX_FIELDS2. For the corresponding constants exposed by the package, see API Reference.

Option

Description

Default

EXPAND_PARAM

Query parameter name for requested expansions.

"expand"

MAXIMUM_EXPANSION_DEPTH

Maximum allowed expansion depth. None means unlimited.

None

FIELDS_PARAM

Query parameter name for sparse field inclusion.

"fields"

OMIT_PARAM

Query parameter name for explicit exclusions.

"omit"

RECURSIVE_EXPANSION_PERMITTED

Whether recursive expansion patterns are allowed.

True

WILDCARD_VALUES

Wildcard values that mean all fields or all expandable fields. Set to None to disable wildcards.

["*", "~all"]

Example:

REST_FLEX_FIELDS2 = {
    "EXPAND_PARAM": "include",
}

Warning

Avoid direct import of the rest_flex_fields2 package in the Django settings. Otherwise the configuration will not be picked up, because the variable does not necessarily exist at the time of the import. Always reference package contents like class names as strings, instead of importing them.

Defining Limits on Serializer Classes

You can set limits directly on a serializer class:

  • maximum_expansion_depth

  • recursive_expansion_permitted

Both settings raise serializers.ValidationError when violated. You can customize the exceptions by overriding recursive_expansion_not_permitted() and expansion_depth_exceeded().

Example:

from rest_flex_fields2.serializers import FlexFieldsModelSerializer


class PersonSerializer(FlexFieldsModelSerializer):
    maximum_expansion_depth = 2
    recursive_expansion_permitted = False

    class Meta:
        model = Person
        fields = ["id", "name", "manager"]
        expandable_fields = {
            "manager": "people.api.serializers.PersonSerializer",
        }

With this configuration, requests such as ?expand=manager.manager.manager raise a validation error.

Serializer Introspection

Instances of FlexFieldsModelSerializer expose expanded_fields, which records the fields expanded during serialization.

serializer = PersonSerializer(
    instance=person,
    context={"request": request},
)
payload = serializer.data
expanded = serializer.expanded_fields

expanded can be used in tests to assert behavior for a specific query.

Wildcards

You can use wildcard values such as * to expand or include all fields at a given level.

Examples:

  • expand=*

  • expand=menu.sections

  • fields=*,restaurant.name,restaurant.address&expand=restaurant

Combining Sparse Fields and Expansion

Sparse fieldsets take precedence over expansion. If a field is not explicitly allowed by fields, it will not be expanded even if it appears in expand.

For example, this request omits country from the response because fields wins:

GET /person/13322?fields=id,name&expand=country

Response:

{
    "id": 13322,
    "name": "John Doe"
}

Utility Functions

For broader endpoint usage patterns that pair with these helpers, see Usage.

rest_flex_fields2.utils.is_expanded(request, field)

Returns whether a field was requested via the active expansion parameter.

rest_flex_fields2.utils.is_included(request, field)

Returns whether a field remains included after fields and omit are applied.

Example view usage:

from rest_flex_fields2.utils import is_expanded
from rest_flex_fields.views import FlexFieldsModelViewSet


class PersonViewSet(FlexFieldsModelViewSet):
    serializer_class = PersonSerializer

    def get_queryset(self):
        queryset = Person.objects.all()

        if is_expanded(self.request, "country"):
            queryset = queryset.select_related("country")

        return queryset

Query Optimization Backend

FlexFieldsFilterBackend is an optional integration that applies queryset optimization based on requested expansions and sparse fieldsets. You do not need this backend to use dynamic expansion (expand) or sparse fieldsets (fields and omit). Those core features work through the serializer layer. But you can add FlexFieldsFilterBackend when you want automatic queryset tuning from request parameters to reduce query count and payload size automatically. It applies select_related(), prefetch_related(), and only() based on the requested fields and expansions.

REST_FRAMEWORK = {
    "DEFAULT_FILTER_BACKENDS": (
        "rest_flex_fields2.filter_backends.FlexFieldsFilterBackend",
    ),
}

Warning

The optimization currently works for one nesting level only. Treat it as a convenience feature, not as a substitute for inspecting your queryset behavior.