API Reference¶
This page documents every public class, function, and exception. It is generated in part from the source docstrings via mkdocstrings — the same text you'll see in your editor's tooltips.
Serializers¶
PartialFieldsSerializerMixin¶
Mixin adding sparse-fieldset support to a DRF serializer.
Combine with :class:rest_framework.serializers.Serializer or
:class:rest_framework.serializers.ModelSerializer (this mixin must
come first in the MRO). Works correctly at arbitrary nesting depth: a
serializer used as a nested field only needs this mixin itself for its
own sub-selection (author(name,email)) to be honored — no manual
context propagation is required.
Example
.. code-block:: python
class AuthorSerializer(PartialFieldsSerializerMixin, serializers.ModelSerializer):
class Meta:
model = Author
fields = ["id", "name", "email", "bio"]
class ArticleSerializer(PartialFieldsSerializerMixin, serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Article
fields = ["id", "title", "body", "author"]
A request to /articles/1/?fields=title,author(name) returns
only title and author.name.
Source code in src/drf_partial_response_fields/serializers.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
get_fields()
¶
Return the field set narrowed to what the client requested.
Returns:
| Type | Description |
|---|---|
dict[str, Field[Any, Any, Any, Any]]
|
An ordered mapping of field name to bound |
dict[str, Field[Any, Any, Any, Any]]
|
class: |
dict[str, Field[Any, Any, Any, Any]]
|
according to the :class: |
dict[str, Field[Any, Any, Any, Any]]
|
resolved for this serializer's position in the response tree. |
Source code in src/drf_partial_response_fields/serializers.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
to_representation(instance)
¶
Serialize instance, applying any requested field aliases.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
Any
|
The object being serialized. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The representation produced by the parent class, with any |
Any
|
|
Source code in src/drf_partial_response_fields/serializers.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
PartialFieldsSerializer¶
Bases: PartialFieldsSerializerMixin, Serializer[Any]
Convenience base combining :class:PartialFieldsSerializerMixin with
:class:rest_framework.serializers.Serializer, for non-model serializers.
Source code in src/drf_partial_response_fields/serializers.py
149 150 151 152 | |
PartialFieldsModelSerializer¶
Bases: PartialFieldsSerializerMixin, ModelSerializer[Any]
Convenience base combining :class:PartialFieldsSerializerMixin with
:class:rest_framework.serializers.ModelSerializer.
Source code in src/drf_partial_response_fields/serializers.py
155 156 157 158 | |
PartialFieldsListSerializer¶
Bases: ListSerializer[Any]
A :class:~rest_framework.serializers.ListSerializer variant that is
a no-op subclass kept for symmetry and forward compatibility.
Field filtering for many=True serializers is handled entirely by
:class:PartialFieldsSerializerMixin on the child serializer (its
_path_from_root correctly skips the list wrapper), so this class
does not need to override any behavior today. It exists so that users
who explicitly set Meta.list_serializer_class have a documented,
stable name to point to.
Source code in src/drf_partial_response_fields/serializers.py
161 162 163 164 165 166 167 168 169 170 171 | |
Views¶
PartialResponseMixin¶
Adds ?fields= support and automatic query optimization to a view.
Mix this into any :class:~rest_framework.generics.GenericAPIView
subclass — including every generic view (ListAPIView,
RetrieveUpdateDestroyAPIView, ...) and every viewset
(ModelViewSet, ReadOnlyModelViewSet, custom
GenericViewSet subclasses) — before the DRF base class in the
MRO:
.. code-block:: python
class ArticleViewSet(PartialResponseMixin, viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
This mixin does two things:
- Injects the parsed
fieldsrequest into the serializer context (via :meth:get_serializer_context), which :class:~drf_partial_response_fields.serializers.PartialFieldsSerializerMixinreads to filter fields. - Rewrites the queryset (via :meth:
get_queryset) to addselect_related,prefetch_related, andonlyso that only the data needed for the requested fields is fetched — see :func:drf_partial_response_fields.optimizer.optimize_queryset.
Both behaviors compose transparently with pagination: optimization happens on the unsliced queryset before the paginator runs, so page size and query cost stay independent of which fields were requested.
Source code in src/drf_partial_response_fields/mixins.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
get_partial_response_fields_tree()
¶
Return (and cache) the parsed fields tree for the current request.
When the :ref:SAFE_METHODS_ONLY <settings-safe-methods-only>
setting is enabled (the default), this returns
:data:~drf_partial_response_fields.tree.ALL_TREE for any request
whose method is not GET, HEAD, or OPTIONS — see the
setting's docstring for why this matters for write endpoints.
Returns:
| Name | Type | Description |
|---|---|---|
The |
FieldTree
|
class: |
FieldTree
|
from this request's |
|
FieldTree
|
cached on the view instance for the lifetime of the request, |
|
FieldTree
|
since a view instance handles exactly one request in DRF. |
Source code in src/drf_partial_response_fields/mixins.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
get_queryset()
¶
Return the view's queryset, optimized for the requested fields.
Returns:
| Type | Description |
|---|---|
Any
|
The queryset produced by the next class in the MRO (e.g. |
Any
|
|
Any
|
func: |
Any
|
when the view's serializer is a |
Any
|
class: |
Any
|
and query optimization is enabled. Non-model serializers, or |
Any
|
optimization disabled via the |
Any
|
setting, leave the queryset untouched. |
Source code in src/drf_partial_response_fields/mixins.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
get_serializer_context()
¶
Return the serializer context with the parsed fields tree attached.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The context dict produced by the next class in the MRO (e.g. |
dict[str, Any]
|
|
dict[str, Any]
|
class: |
dict[str, Any]
|
under |
dict[str, Any]
|
data: |
Source code in src/drf_partial_response_fields/mixins.py
118 119 120 121 122 123 124 125 126 127 128 129 130 | |
parse_request_fields¶
Parse the fields query parameter off an in-flight request.
Use this directly in a plain :class:~rest_framework.views.APIView
(which :class:PartialResponseMixin cannot hook into automatically)
to build the context dict for a serializer by hand:
.. code-block:: python
class ArticleDetailView(APIView):
def get(self, request, pk):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(
article,
context={
"request": request,
PARTIAL_RESPONSE_FIELDS_CONTEXT_KEY: parse_request_fields(request),
},
)
return Response(serializer.data)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
Request
|
The current DRF :class: |
required |
Returns:
| Type | Description |
|---|---|
FieldTree
|
The parsed :class: |
FieldTree
|
this request, using the configured |
FieldTree
|
and |
Raises:
| Type | Description |
|---|---|
InvalidFieldsParameterError
|
If the query parameter value is not syntactically valid. |
Source code in src/drf_partial_response_fields/mixins.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
PARTIAL_RESPONSE_FIELDS_CONTEXT_KEY¶
A module-level constant: the serializer-context key under which
PartialResponseMixin stores the parsed FieldTree for the current
request. Public alias of drf_partial_response_fields.constants.CONTEXT_KEY,
for use by manual (non-mixin) integrations such as plain APIView
subclasses — see Advanced Usage.
Query optimization¶
optimize_queryset¶
Apply select_related / prefetch_related / only to a queryset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queryset
|
QuerySet[Any]
|
The base queryset to optimize. It is not mutated; a new queryset is returned. |
required |
serializer_class
|
type[Serializer[Any]]
|
The (potentially nested) serializer class that
will render the queryset's results. Must ultimately be a
:class: |
required |
tree
|
FieldTree
|
The parsed field restriction for the top level of the
response (as produced by
:func: |
required |
strict
|
bool | None
|
Whether unknown field names should raise. Defaults to the
:ref: |
None
|
required_only_fields
|
frozenset[str]
|
Field names that must be included in
|
frozenset()
|
Returns:
| Type | Description |
|---|---|
QuerySet[Any]
|
A new queryset with the relevant |
QuerySet[Any]
|
|
QuerySet[Any]
|
fields include nothing optimizable, the original queryset is |
QuerySet[Any]
|
returned unchanged. |
Raises:
| Type | Description |
|---|---|
UnknownFieldError
|
If
|
Source code in src/drf_partial_response_fields/optimizer.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
Decorators¶
requires_related¶
Declare the relations a get_<field> method depends on.
Attach this to a :class:~rest_framework.serializers.SerializerMethodField
method so that :func:drf_partial_response_fields.optimizer.optimize_queryset
includes the declared relations in the generated queryset — but only
when a client actually requests the field, avoiding the cost when it is
not needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
select_related
|
Sequence[str]
|
Dotted relation paths to add to |
()
|
prefetch_related
|
Sequence[str]
|
Dotted relation paths to add to
|
()
|
Returns:
| Type | Description |
|---|---|
Callable[[_F], _F]
|
A decorator that attaches the hints to the wrapped method and |
Callable[[_F], _F]
|
returns it unchanged. |
Example
.. code-block:: python
class ArticleSerializer(PartialFieldsSerializerMixin, serializers.ModelSerializer):
editor_name = serializers.SerializerMethodField()
@requires_related(select_related=["editor__profile"])
def get_editor_name(self, obj):
return obj.editor.profile.display_name
Source code in src/drf_partial_response_fields/decorators.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
OptimizationHints¶
Extra select_related / prefetch_related paths for one field.
Attributes:
| Name | Type | Description |
|---|---|---|
select_related |
tuple[str, ...]
|
Relation paths (Django |
prefetch_related |
tuple[str, ...]
|
Relation paths that must be fetched via
|
Source code in src/drf_partial_response_fields/decorators.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
get_hints¶
Return the :class:OptimizationHints attached to func, if any.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
object
|
A bound or unbound method, typically a serializer's
|
required |
Returns:
| Type | Description |
|---|---|
OptimizationHints | None
|
The attached :class: |
OptimizationHints | None
|
was never decorated with :func: |
Source code in src/drf_partial_response_fields/decorators.py
88 89 90 91 92 93 94 95 96 97 98 99 | |
Parsing¶
parse_fields¶
Parse a raw fields query-parameter value into a :class:FieldTree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw
|
str
|
The raw string value of the query parameter, e.g.
|
required |
max_depth
|
int
|
Maximum allowed parenthesis nesting depth. Guards against pathological input designed to exhaust the parser's call stack. |
6
|
max_length
|
int
|
Maximum allowed length of |
2000
|
Returns:
| Type | Description |
|---|---|
FieldTree
|
The parsed, immutable :class: |
Raises:
| Type | Description |
|---|---|
InvalidFieldsParameterError
|
If
|
Example
tree = parse_fields("id,author(name,email)") tree.mode 'include' sorted(tree.includes) ['author', 'id']
Source code in src/drf_partial_response_fields/parser.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
Data model¶
FieldTree¶
An immutable tree describing which fields to include at one level.
Attributes:
| Name | Type | Description |
|---|---|---|
mode |
TreeMode
|
|
includes |
Mapping[str, FieldSpec]
|
Mapping of field name to :class: |
excludes |
frozenset[str]
|
The set of excluded field names, populated only when
|
Source code in src/drf_partial_response_fields/tree.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
FieldSpec¶
A single requested field within a :class:FieldTree.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The concrete field name as it appears on the serializer. |
alias |
str | None
|
The key the field should be renamed to in the response, or
|
children |
FieldTree | None
|
A nested :class: |
Source code in src/drf_partial_response_fields/tree.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
ALL_TREE¶
resolve_allowed_names¶
Compute the set of field names allowed by tree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tree
|
FieldTree
|
The parsed field restriction for this level. |
required |
available
|
Collection[str]
|
The full set of field names that exist at this level
(e.g. every key in a serializer's |
required |
strict
|
bool
|
If |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
The subset of |
Raises:
| Type | Description |
|---|---|
UnknownFieldError
|
If
|
Source code in src/drf_partial_response_fields/tree.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
child_tree¶
Descend one level into tree following field name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tree
|
FieldTree
|
The tree at the current level. |
required |
name
|
str
|
The field name to descend into. |
required |
Returns:
| Type | Description |
|---|---|
FieldTree
|
The nested :class: |
FieldTree
|
data: |
FieldTree
|
because |
FieldTree
|
without an explicit nested group, or |
FieldTree
|
mode, which never restricts what happens within a kept field). |
Source code in src/drf_partial_response_fields/tree.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
Exceptions¶
PartialResponseFieldsError¶
Bases: ValidationError
Base class for all errors raised by this package.
Catch this class if you want to handle any error originating from
drf-partial-response-fields without depending on the more specific
subclasses.
Source code in src/drf_partial_response_fields/exceptions.py
15 16 17 18 19 20 21 22 23 | |
InvalidFieldsParameterError¶
Bases: PartialResponseFieldsError
Raised when the fields query parameter cannot be parsed.
This covers syntax errors such as unbalanced parentheses, empty field names, invalid characters, ambiguous combinations of inclusion and exclusion within the same group, and expressions that exceed the configured maximum nesting depth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
A human-readable description of the syntax error, including the offending fragment where possible. |
required |
Example
from drf_partial_response_fields.parser import parse_fields parse_fields("author(name") Traceback (most recent call last): ... drf_partial_response_fields.exceptions.InvalidFieldsParameterError: ...
Source code in src/drf_partial_response_fields/exceptions.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
UnknownFieldError¶
Bases: PartialResponseFieldsError
Raised when a requested field does not exist on the serializer.
Only raised when the
:ref:STRICT <settings-strict> setting is enabled. When STRICT is
disabled (the default), unknown field names are silently ignored so
that clients cannot probe for the existence of hidden fields.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
A human-readable description naming the unknown field(s). |
required |
Source code in src/drf_partial_response_fields/exceptions.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
Settings¶
get_setting¶
Return the effective value of a single package setting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
One of the keys documented in :data: |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The user-configured value if present in the |
Any
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
ImproperlyConfigured
|
If the
|
Source code in src/drf_partial_response_fields/settings.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
See Settings for the full list of recognized keys and their defaults.
OpenAPI (drf-spectacular)¶
Requires the openapi extra: pip install drf-partial-response-fields[openapi].
fields_query_parameter¶
Build an :class:~drf_spectacular.utils.OpenApiParameter for fields.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
description
|
str | None
|
Custom description text. Defaults to a general explanation of the sparse-fieldset syntax. |
None
|
Returns:
| Type | Description |
|---|---|
OpenApiParameter
|
An |
OpenApiParameter
|
setting, suitable for passing to |
Example
.. code-block:: python
from drf_spectacular.utils import extend_schema
from drf_partial_response_fields.openapi import fields_query_parameter
@extend_schema(parameters=[fields_query_parameter()])
class ArticleViewSet(PartialResponseMixin, viewsets.ModelViewSet):
...
Source code in src/drf_partial_response_fields/openapi.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
PartialResponseAutoSchema¶
Bases: AutoSchema
A drf-spectacular AutoSchema that documents ?fields= automatically.
Assign this to a view's schema attribute (or set it as the project
default via SPECTACULAR_SETTINGS["DEFAULT_GENERATOR_CLASS"] /
per-view schema =) to have the fields query parameter appear in
the generated OpenAPI schema for every action, without repeating
@extend_schema on each view.
Source code in src/drf_partial_response_fields/openapi.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
get_override_parameters()
¶
Return drf-spectacular's normal override parameters plus fields.
Returns:
| Type | Description |
|---|---|
list[Any]
|
The list of parameters from the parent implementation with a |
list[Any]
|
func: |
Source code in src/drf_partial_response_fields/openapi.py
77 78 79 80 81 82 83 84 85 86 | |