rest_framework_dso.fields module

class rest_framework_dso.fields.AbstractEmbeddedField(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)

Bases: object

A ‘virtual’ field that contains the configuration of an embedded field.

Note this virtual field is not part of the serializer.fields, thus it’s also not copied per instance. It’s not possible to store request-state (such as the parent serializer object) in this class.

There are two ways to include an embedded field in the serializer. Either add it as a class attribute (it will auto-register in Meta.embedded_fields), or add it directly in Meta.embedded_fields. Both styles require the serializer class to inherit from rest_framework_dso.serializers.ExpandableSerializer.

The embedded fields are designed to be efficient during streaming rendering of large datasets. Instead of collecting/prefetching the whole queryset in one go, the required relationship data is incrementally collected as each individual rendered object is written to the client. After rendering the whole first list of objects, the related objects can now be queried in a single SQL statement and be written to the next section in the "_embedded": { ... } dict.

Hence, there are 2 significant overrides to implement: the get_related_ids() method and related_id_field attribute. These define how a relationship is queried and should allow spanning FK/M2M and reverse ORM relations by playing with those 2 overrides.

__init__(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)
bind(parent_serializer_class: type[rest_framework.serializers.Serializer], field_name: str)

Return the “ID” values that are referenced from a single instance This can be a FK or an NM relationship.

get_serializer(parent: Serializer, **kwargs) Serializer

Build the EmbeddedField serializer object that can generate an embedded result.

Since this virtual-field object persists between all sessions, the parent/root serializer needs to be provided here. Settings like fields_to_extend are provided via the **kwargs.

is_array

Whether the relation returns an list of items (e.g. ManyToMany).

is_loose

Signals that the relation only links to the first part of a foreign composite key

is_reverse

Whether the relation is actually a reverse relationship.

parent_model

Return the Django model class

property related_id_field: Optional[str]

The ID field is typically auto-detected.

It can however be overwritten to change the object retrieval query. This is used by reverse relationships to retrieve objects from a related foreign key instead.

related_model

Return the Django model class

source_field
class rest_framework_dso.fields.DSOGeometryField(*args, **kwargs)

Bases: GeometryField

Extended geometry field to properly handle export formats.

to_internal_value(value)

Make sure that parsing remote data (e.g. proxy API) will set the correct CRS.

to_representation(value)

Avoid GeoJSON export format for e.g. CSV exports

class rest_framework_dso.fields.DSORelatedLinkField(*args, **kwargs)

Bases: HyperlinkedRelatedField

A field that generates the proper structure of an object in the _links section. This generates a “title” and “href”..

class rest_framework_dso.fields.DSOSelfLinkField(*args, **kwargs)

Bases: DSORelatedLinkField, HyperlinkedIdentityField

The link object for a link to ‘self’.

This implementation is solely done by inheritance, as the ‘HyperlinkedIdentityField’ is an ‘HyperlinkedRelatedField’ underneath with the parameters source="*", read_only="True".

class rest_framework_dso.fields.DSOURLField(*args, **kwargs)

Bases: URLField

Ensure the URL is properly encoded

to_representation(value)

Transform the outgoing native value into primitive data.

class rest_framework_dso.fields.EmbeddedField(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)

Bases: AbstractEmbeddedField

An embedded field for a foreign-key relation.

This collects the identifiers to the related foreign objects, so these can be queried once all main objects have been written to the client.

attname

Find the _id field value(s)

class rest_framework_dso.fields.EmbeddedManyToManyField(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)

Bases: AbstractEmbeddedField

An embedded field for a M2M relation.

This collects all identifiers of the primary objects, so the through table can be queried afterwards in a single call to find all related objects.

The PK of this source object can be used to find the relation in the through table.

get_serializer(parent: Serializer, **kwargs) Serializer

Build the EmbeddedField serializer object that can generate an embedded result.

Since this virtual-field object persists between all sessions, the parent/root serializer needs to be provided here. Settings like fields_to_extend are provided via the **kwargs.

related_id_field
class rest_framework_dso.fields.EmbeddedManyToManyRelField(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)

Bases: EmbeddedManyToManyField

Embedded field for reverse M2M relations.

This performs roughly the same query as the forward M2M relation, except that the relation to the through table is followed backwards.

related_id_field
class rest_framework_dso.fields.EmbeddedManyToOneRelField(serializer_class: type[rest_framework.serializers.Serializer], *, source=None)

Bases: EmbeddedField

An embedded field for reverse relations (of foreign keys).

This collects the identifiers of all primary objects, so any objects that link to those primary objects can be resolved afterwards in a single query.

The name of this object is somewhat awkward, but it follows Django conventions. Django ForeignKey’s have a OneToManyRel that describes the relationship. That object is also placed on the foreign object as reverse field, thus giving the funny ManyToOneRel.one_to_many == True situation. The reverse field should have been called something like “OneToManyField” but Django reuses the “ManyToOneRel” there.

property attname: str

Reverse relations are based on the current object’s identifier.

Reverse relations link to the given instance, hence we track the ‘pk’.

property related_id_field

Change the ID field to implement reverse relations. This lets the results be read from the remote foreign key to retrieve the objects.

class rest_framework_dso.fields.FieldsToDisplay(fields: Optional[list[str]] = None, prefix: str = '')

Bases: object

Tell which fields should be displayed in the response.

This object type helps to track nesting levels of fields to render, e.g. ?_fields=id,code,customer.id,customer.name. It also handles exclusions across nesting levels, e.g. ?_fields=-customer.name.

__init__(fields: Optional[list[str]] = None, prefix: str = '')
allow_nested(field_name) bool

Whether a field can be used for nesting

apply(fields: dict[str, rest_framework.fields.Field], valid_names: Iterable[str], always_keep: Iterable[str]) dict[str, rest_framework.fields.Field]

Reduce the fields from a serializer based on the current context. This returns a new dictionary that can be assigned to serializer.fields.

as_nested(field_name) FieldsToDisplay

Return a new instance that starts at a nesting level. An empty result is returned when the field does not allow nesting, or isn’t mentioned.

property children: Iterable[str]

Tell which sub-objects will have exclusions

property excludes: Iterable[str]

Tell which fields must not be displayed.

get_allow_list(valid_names: set[str]) tuple[set[str], set[str]]

Find out which fields should be included. This transforms the include/exclude behavior into a positive list of fields that should be kept.

property includes: Iterable[str]

Tell which fields must be included. Note that any item in children should also be considerd for inclusion.

reduced()

Whether the returned fields need to be reduced. Note that this returns false when there are child nodes that need to be reduced. These are found with allow_nested(), as_nested() and children.

class rest_framework_dso.fields.GeoJSONIdentifierField(*args, **kwargs)

Bases: Field

A field that renders the “id” field for a GeoJSON feature.

__init__(model=None, **kwargs)
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.

to_representation(value)

Transform the outgoing native value into primitive data.

rest_framework_dso.fields.get_embedded_field_class(model_field: Union[RelatedField, ForeignObjectRel]) type[rest_framework_dso.fields.AbstractEmbeddedField]

Return the embedded field type that is suited for a particular model field.