rest_framework_dso.serializers module
The serializers implement additional DSO responses features.
Most features can be implemented by the following means:
Having the proper set of “fields” loaded in the serializer. These field classes determine the format of individual data types.
Overriding
to_representation()
where needed.
There are 2 layers of serializers, just like standard DRF:
DSOSerializer
and it’s cousinDSOListSerializer
that’s used formany=True
.
The non-model serializers implement the bits that are not dependant on database ORM logic like models or querysets. These serializers are therefore more limited in functionality, but useful to implement DSO-style responses for other data sources (e.g. remote API responses).
The model-serializers depend on the ORM logic, and support features like object embedding and constructing serializer fields based on the model field metadata.
- class rest_framework_dso.serializers.DSOListSerializer(*args, **kwargs)
Bases:
ExpandableSerializer
,ListSerializer
Fix pagination for lists.
This should be used together with the DSO…Pagination class when results are paginated. It outputs the
_embedded
section for the HAL-JSON spec: https://tools.ietf.org/html/draft-kelly-json-hal-08- __init__(*args, results_field=None, **kwargs)
Allow to override the
results_field
on construction
- bind(field_name, parent)
Initializes the field name and parent for the field instance. Called when a field is added to the parent serializer instance.
- property data
- expanded_fields
Retrieve the embedded fields for this serializer
- requires_context = True
- results_field = None
The field name for the results envelope
- class rest_framework_dso.serializers.DSOModelListSerializer(*args, **kwargs)
Bases:
DSOListSerializer
Perform object embedding for lists.
This subclass implements the ORM-specific bits that the
DSOListSerializer
can’t provide.This should be used together with the DSO…Pagination class when results are paginated. It outputs the
_embedded
section for the HAL-JSON spec: https://tools.ietf.org/html/draft-kelly-json-hal-08- get_prefetch_lookups() list[Union[django.db.models.query.Prefetch, str]]
Tell which fields should be included for a
prefetch_related()
.
- get_queryset_iterator(queryset: QuerySet) Iterable[Model]
Get the most optimal iterator to traverse over a queryset.
- to_representation(data)
Improved list serialization.
It includes the data for the HAL “_embedded” section.
It reads the database with a streaming iterator to reduce memory.
It collects any embedded sections, and queries them afterwards
- class rest_framework_dso.serializers.DSOModelSerializer(*args, **kwargs)
Bases:
DSOSerializer
,DSOModelSerializerBase
DSO-compliant serializer for Django models.
This serializer can be used inside a list (by
DSOModelListSerializer
whenmany=True
is given), or standalone for a detail page.This supports the following extra’s:
The self-URL can be generated when this serializer is used for a
_links
section.Embedded relations are returned in an
_embedded
section.
To use the embedding feature, include an
EmbeddedField
field in the class:class SomeSerializer(DSOModelSerializer): embedded_field = EmbeddedField(SerializerClass) class Meta: model = ... fields = [...]
The embedded support works on all relational fields.
- to_representation(instance)
Check whether the geofields need to be transformed.
- class rest_framework_dso.serializers.DSOModelSerializerBase(*args, **kwargs)
Bases:
HyperlinkedModelSerializer
A base serializer that only handles the field layout.
This base class does not do any request parameter handling at all.
- serializer_field_mapping = {<class 'django.db.models.fields.AutoField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.BigIntegerField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.BooleanField'>: <class 'rest_framework.fields.BooleanField'>, <class 'django.db.models.fields.CharField'>: <class 'rest_framework.fields.CharField'>, <class 'django.db.models.fields.CommaSeparatedIntegerField'>: <class 'rest_framework.fields.CharField'>, <class 'django.db.models.fields.DateField'>: <class 'rest_framework.fields.DateField'>, <class 'django.db.models.fields.DateTimeField'>: <class 'rest_framework.fields.DateTimeField'>, <class 'django.db.models.fields.DecimalField'>: <class 'rest_framework.fields.DecimalField'>, <class 'django.db.models.fields.DurationField'>: <class 'rest_framework.fields.DurationField'>, <class 'django.db.models.fields.EmailField'>: <class 'rest_framework.fields.EmailField'>, <class 'django.db.models.fields.Field'>: <class 'rest_framework.fields.ModelField'>, <class 'django.db.models.fields.files.FileField'>: <class 'rest_framework.fields.FileField'>, <class 'django.db.models.fields.FloatField'>: <class 'rest_framework.fields.FloatField'>, <class 'django.db.models.fields.files.ImageField'>: <class 'rest_framework.fields.ImageField'>, <class 'django.db.models.fields.IntegerField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.NullBooleanField'>: <class 'rest_framework.fields.BooleanField'>, <class 'django.db.models.fields.PositiveIntegerField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.PositiveSmallIntegerField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.SlugField'>: <class 'rest_framework.fields.SlugField'>, <class 'django.db.models.fields.SmallIntegerField'>: <class 'rest_framework.fields.IntegerField'>, <class 'django.db.models.fields.TextField'>: <class 'rest_framework.fields.CharField'>, <class 'django.db.models.fields.TimeField'>: <class 'rest_framework.fields.TimeField'>, <class 'django.db.models.fields.URLField'>: <class 'rest_framework_dso.fields.DSOURLField'>, <class 'django.db.models.fields.UUIDField'>: <class 'rest_framework.fields.UUIDField'>, <class 'django.db.models.fields.GenericIPAddressField'>: <class 'rest_framework.fields.IPAddressField'>, <class 'django.db.models.fields.FilePathField'>: <class 'rest_framework.fields.FilePathField'>, <class 'django.db.models.fields.json.JSONField'>: <class 'rest_framework.fields.JSONField'>, <class 'django.contrib.postgres.fields.hstore.HStoreField'>: <class 'rest_framework.fields.HStoreField'>, <class 'django.contrib.postgres.fields.array.ArrayField'>: <class 'rest_framework.fields.ListField'>, <class 'django.contrib.postgres.fields.jsonb.JSONField'>: <class 'rest_framework.fields.JSONField'>, <class 'django.contrib.gis.db.models.fields.GeometryField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.PointField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.LineStringField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.PolygonField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.MultiPointField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.MultiLineStringField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.MultiPolygonField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>, <class 'django.contrib.gis.db.models.fields.GeometryCollectionField'>: <class 'rest_framework_dso.fields.DSOGeometryField'>}
Define that relations will also be generated as {“href”: …, “title”: …}.
alias of
DSORelatedLinkField
- serializer_url_field
alias of
DSOSelfLinkField
- url_field_name = 'self'
- class rest_framework_dso.serializers.DSOSerializer(*args, **kwargs)
Bases:
ExpandableSerializer
,Serializer
Basic non-model serializer logic.
This class implements all logic that can be used by all serializers, including those which are not based on database models:
Geometry values are converted into a single coordinate reference system.
The
?_fields
parameter can limit the returned fields.request.response_content_crs
is filled with the used CRS value.
The geometry values are transformed using the
CRS
object found inrequest.accept_crs
.- __init__(*args, fields_to_display=None, **kwargs)
- expanded_fields
Retrieve the embedded fields for this serializer
- fields_always_included = {'_links'}
- fields_param = '_fields'
- property fields_to_display: FieldsToDisplay
Define which fields should be included only.
- get_fields() dict[str, rest_framework.fields.Field]
Override DRF logic so fields can be removed from the response.
When looking deeper inside DRF logic, you’ll find that
get_fields()
makes a deepcopy ofself._declared_fields
. This approach allows making changes to the statically defined fields on this serializer instance. Only once all fields are created, the mapping is assigned to self.fields andfield.bind()
is called on each field. At that point, the fields know their own field name and serializer parent.Omitting a field from the serializer is the most efficient way to avoid returning data, since the serializer won’t query/format the data at all. This may also avoid additional queries in case of relational fields.
- get_valid_field_names(fields: dict[str, rest_framework.fields.Field]) set[str]
Tell which fields are valid to use in the
?_fields=..
query. This returns additional entries for relationships and expandable (virtual)fields, as these should not trigger error messages when those names are mentioned.
- limit_return_fields(fields: dict[str, rest_framework.fields.Field]) dict[str, rest_framework.fields.Field]
Tell which fields should be included in the response. Any field that is omitted will not be outputted, nor queried.
- classmethod many_init(*args, **kwargs)
The initialization for many=True.
This overrides the default
list_serializer_class
so it also returns HAL-style pagination and possibly embedding.
- requires_context = True
- to_representation(instance)
Check whether the geofields need to be transformed.
This method also sets
request.response_content_crs
so the response rendering can tell which Coordinate Reference System is used by all geometry fields.
- class rest_framework_dso.serializers.ExpandableSerializer(*args, **kwargs)
Bases:
BaseSerializer
A serializer class that handles ?_expand / ?_expandScope parameters.
This is a separate class because the parameter needs to be handled in 2 separate classes:
DSOListSerializer
and the regularDSOSerializer
.This class can be added as a mixin in case the serializer should be a
ModelSerializer
orListSerializer
.- __init__(*args, fields_to_expand=<class 'rest_framework.fields.empty'>, **kwargs)
- expand_all_param = '_expand'
- expand_field = '_embedded'
- expand_param = '_expandScope'
- property expand_scope: ExpandScope
Retrieve the requested expand. For the top-level serializer the request is parsed. Deeper nested serializers only return expand information when this is explicitly provided by their parent serializer.
- property expanded_fields: list[rest_framework_dso.embedding.EmbeddedFieldMatch]
Retrieve the embedded fields for this request.
- classmethod get_embedded_field(field_name, prefix='') AbstractEmbeddedField
Retrieve an embedded field from the serializer class.
- get_embedded_objects_by_id(embedded_field: AbstractEmbeddedField, id_list: list[Union[str, int]]) Union[QuerySet, Iterable[Model]]
Retrieve a number of embedded objects by their identifier.
While the embedded field typically collects the related objects by their primary key, the reverse and M2M field types use a custom identifier to find the related objects through a different/reverse relationship.
This method can be overwritten to support other means of object retrieval, e.g. fetching the objects from a remote endpoint. When an queryset is returned, it will be optimized to run most efficiently with relationships.
- has_expand_scope_override() bool
Tell whether the ‘fields_to_expand’ is set by the code instead of request.
- is_toplevel
Tell whether the current serializer is the top-level serializer. Nested serializers shouldn’t handle request-parsing logic.
- class rest_framework_dso.serializers.HALRawIdentifierLinkSerializer(*args, **kwargs)
Bases:
Serializer
Tagging interface to recognize serializers that don’t receive objects.
This is an empty class that is used to tag a ‘_links’ subfield that only receives a raw identifier as its ‘source’ value. This information is necessary to determine the runtime behavior, for example when resolving the prefetch lookups for a queryset.