fairdm.api.serializers#

Serializer base classes for projects, datasets, samples, measurements and contributors.

Module Contents#

Classes#

CreatorCreditMixin

Credit the person who creates a record through the API, and hold back what needs manage.

RecordReferenceField

Refer to a record by its short identifier and its address in the API.

RecordURLField

The address of a record in the API, whatever type the record is.

PortalPageField

The address of a record’s own page on the portal’s website.

GeoJSONPointField

A record’s location as a GeoJSON Point, longitude first, in WGS 84.

RecordListSerializer

List serializer that checks every reference on a page of records at once.

DescriptionSerializer

A typed description of a record, its type given by the concept’s address.

DateSerializer

A typed key date of a record, as a year, a month or a day, its type given by address.

IdentifierSerializer

A typed external identifier of a record, its type given by the concept’s address.

ConceptSerializer

A concept: its address, its notation and its name in the reading language.

KeywordSerializer

A controlled keyword of a record and the address of the vocabulary it comes from.

RoleSerializer

A role a contributor holds on a record.

NameIdentifierSerializer

An identifier of a credited contributor, as DataCite gives a name identifier.

OrganizationReferenceSerializer

An organization named by its short identifier, its address in the API and its name.

CreditAffiliationSerializer

The organization a contributor is credited from, as DataCite gives an affiliation.

ContributionListSerializer

The credits of a record: those that still name a contributor, each with its names.

ContributionSerializer

A credit on a record, with what DataCite asks of a creator or contributor.

LicenseSerializer

The licence a dataset is published under.

RecordSerializer

Serializer for a project, dataset, sample or measurement.

ProjectSerializer

A project with its owner and its metadata.

DatasetSerializer

A dataset with its project, its licence and its metadata.

BaseSampleSerializer

Base DRF serializer for all Sample subtypes.

BaseMeasurementSerializer

Base DRF serializer for all Measurement subtypes.

ContributorIdentifierSerializer

An identifier of a contributor, such as an ORCID iD, its type’s address and its own.

ContributorRecordsMixin

Gives a contributor the addresses of the project and dataset lists narrowed to them.

PersonListSerializer

A person as the people list shows them: who they are and where they mainly belong.

AffiliationTypeField

The level of an affiliation, given as the lower-case name of its membership type.

AffiliationSerializer

A verified affiliation of a person: the organization, the kind, and the dates.

PersonSerializer

A single person, as far as their public profile page shows.

OrganizationListSerializer

An organization as the organizations list shows it.

PersonReferenceSerializer

A person named by their short identifier, their address in the API and their name.

MemberSerializer

A person who belongs to an organization, and the kind of affiliation they hold.

OrganizationSerializer

A single organization, as far as its public profile page shows.

BaseSerializerMixin

Mixin that adds a url hyperlinked field to a serializer that sets its view_name.

API#

class CreatorCreditMixin#

Credit the person who creates a record through the API, and hold back what needs manage.

Visibility and the record a record sits under decide who can get in, so changing either needs the manage level on the record, as on the update forms.

Attributes: manager_only_fields: The names of the fields only someone who can manage the record may change.

manager_only_fields#

(‘visibility’, ‘owner’, ‘project’, ‘dataset’, ‘sample’)

get_fields()#

Offer as a parent only the records the requesting user holds the edit level on.

The same choices the forms give for a project, dataset or sample field, so a record can only be created or moved into a parent the user may edit. A record being updated also keeps its current parent as a choice, so a request that repeats it is not refused.

Returns: The serializer’s fields.

static differs(instance, name, value) → bool#

Say whether a value sent for a field is not what the record already holds.

A parent is compared by primary key: the field offers a sample as its base class and the record holds it as its own type, which Django does not call equal.

Args: instance: The record being updated. name: The name of the field. value: The validated value sent for it.

Returns: True when the value would change the record.

create(validated_data)#

Create the record, then list the requesting user on it at the manage level.

Args: validated_data: The validated fields of the new record.

Returns: The new record.

update(instance, validated_data)#

Update the record, refusing what only a manager may change, or a move that strands it.

Args: instance: The record to update. validated_data: The validated fields to set.

Returns: The updated record.

Raises: PermissionDenied: When a manager-only field would change and the requesting user cannot manage the record. serializers.ValidationError: When the new project or dataset would leave nobody who can sign in able to manage the record.

class RecordReferenceField(**kwargs)#

Bases: rest_framework.serializers.SlugRelatedField

Refer to a record by its short identifier and its address in the API.

A record is returned as {"uuid": ..., "url": ...}, or as None when the requesting user may not see it, by the rule :class:~fairdm.api.filters.FairDMVisibilityFilter applies to a list. A bare identifier or the returned object is accepted. A database number is refused, like any identifier that names no record.

A page of records is checked in one query: :class:RecordListSerializer calls :meth:prime with the page before it is serialized.

Initialization

Look records up by uuid unless told otherwise.

Args: **kwargs: Passed to SlugRelatedField. A queryset makes the field writable.

static route_name(record) → str#

Return the name of the route that serves one record.

Args: record: A project, dataset, sample, measurement or contributor.

Returns: The route name in the api namespace.

static hidden_contributor_pks(context) → set#

Say which contributors the people list leaves out, asking once per request.

Args: context: The serializer context of the request, which keeps the answer.

Returns: The primary keys of superusers and of the anonymous account.

visible_pks(model, pks) → set#

Say which of the records the requesting user may see.

Args: model: The model, or a subclass of it, the records belong to. pks: The primary keys to check.

Returns: The primary keys the user may see.

prime(records, many: str | None = None) → None#

Check the records this field refers to in a page of records, in one query.

Args: records: The page of records about to be serialized. many: The name of the many-to-many relation this field is the child of, if it is.

is_visible(record) → bool#

Say whether the requesting user may see a record.

Args: record: The record referred to.

Returns: True when the user may see it.

to_internal_value(data)#

Accept an identifier, or an object carrying one as uuid.

to_representation(record)#

Return the record’s identifier and address, or None when it is hidden.

get_choices(cutoff=None)#

Key the choices by identifier, as the browsable pages need a hashable key.

class RecordURLField(**kwargs)#

Bases: rest_framework.serializers.HyperlinkedIdentityField

The address of a record in the API, whatever type the record is.

Initialization

Look the record up by uuid; the route comes from the record itself.

Args: **kwargs: Passed to HyperlinkedIdentityField.

get_url(obj, view_name, request, format)#

Build the address from the route that serves this record’s type.

class PortalPageField(**kwargs)#

Bases: rest_framework.serializers.ReadOnlyField

The address of a record’s own page on the portal’s website.

The address is absolute when the serializer has a request, and the path alone when it has none.

Initialization

Read the whole record, as the address comes from its method.

Args: **kwargs: Passed to ReadOnlyField.

to_representation(value) → str#

Return the address of the record’s page.

Args: value: The record or contributor.

Returns: The absolute address, or the path when there is no request.

class GeoJSONPointField(**kwargs)#

Bases: rest_framework.serializers.Field

A record’s location as a GeoJSON Point, longitude first, in WGS 84.

The record’s elevation is the third coordinate where it holds one. A record with no location gives None. The uncertainty is not part of GeoJSON and is a field of its own.

Initialization

Read the whole record, as the elevation sits beside the point, and never write.

Args: **kwargs: Passed to Field.

to_representation(value) → dict | None#

Give the record’s point as a GeoJSON geometry.

Args: value: The sample, measurement or organization.

Returns: The geometry, or None when the record has no location.

class RecordListSerializer(*args, **kwargs)#

Bases: rest_framework.serializers.ListSerializer

List serializer that checks every reference on a page of records at once.

Initialization

to_representation(data)#

Prime each reference field with the whole page, then serialize each record.

class DescriptionSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A typed description of a record, its type given by the concept’s address.

Initialization

type#

‘CharField(…)’

value#

‘CharField(…)’

class DateSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A typed key date of a record, as a year, a month or a day, its type given by address.

Initialization

type#

‘CharField(…)’

value#

‘CharField(…)’

class IdentifierSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A typed external identifier of a record, its type given by the concept’s address.

Initialization

type#

‘CharField(…)’

value#

‘CharField(…)’

class ConceptSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A concept: its address, its notation and its name in the reading language.

Initialization

uri#

‘CharField(…)’

name#

‘SerializerMethodField(…)’

label#

‘CharField(…)’

get_name(concept) → str#

Give the concept’s notation, or an empty string when it has none.

class KeywordSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.ConceptSerializer

A controlled keyword of a record and the address of the vocabulary it comes from.

Initialization

vocabulary#

‘CharField(…)’

class RoleSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.ConceptSerializer

A role a contributor holds on a record.

Initialization

class NameIdentifierSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

An identifier of a credited contributor, as DataCite gives a name identifier.

Initialization

name_identifier#

‘SerializerMethodField(…)’

name_identifier_scheme#

‘SerializerMethodField(…)’

scheme_uri#

‘SerializerMethodField(…)’

get_name_identifier(identifier) → str#

Give the address the identifier resolves to, or its value where it has none.

get_name_identifier_scheme(identifier) → str#

Give the identifier type’s notation, the scheme name DataCite uses.

get_scheme_uri(identifier) → str | None#

Give the address of the scheme’s resolver, or nothing for an unknown scheme.

class OrganizationReferenceSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

An organization named by its short identifier, its address in the API and its name.

Initialization

uuid#

‘CharField(…)’

url#

‘RecordURLField(…)’

name#

‘CharField(…)’

class CreditAffiliationSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.OrganizationReferenceSerializer

The organization a contributor is credited from, as DataCite gives an affiliation.

The identifier is the organization’s ROR ID where it has one, and otherwise its first.

Initialization

affiliation_identifier#

‘SerializerMethodField(…)’

affiliation_identifier_scheme#

‘SerializerMethodField(…)’

scheme_uri#

‘SerializerMethodField(…)’

static identifier_of(organization)#

Pick the identifier to give: its ROR ID, else the first it holds.

Args: organization: The organization credited from.

Returns: The identifier, or None when the organization holds none.

get_affiliation_identifier(organization) → str | None#

Give the address the identifier resolves to, or its value where it has none.

get_affiliation_identifier_scheme(organization) → str | None#

Give the kind of the identifier, as its type’s notation.

get_scheme_uri(organization) → str | None#

Give the address of the identifier’s scheme, or nothing for an unknown scheme.

class ContributionListSerializer(*args, **kwargs)#

Bases: rest_framework.serializers.ListSerializer

The credits of a record: those that still name a contributor, each with its names.

A person’s given and family name come from an annotation on the credit queryset when the record was loaded for a read. A credit without them, as in the body that answers a create or an update, has them read for the whole list with one query.

Initialization

to_representation(data)#

Leave out a credit whose contributor was deleted, then serialize the rest.

class ContributionSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A credit on a record, with what DataCite asks of a creator or contributor.

The credit names the person or organization, their identifiers, the organization recorded on the credit and the roles held. The access level a credit carries is not shown, as the record’s page does not show it. A credit held by an account the people list leaves out has no uuid and no url.

Initialization

uuid#

‘SerializerMethodField(…)’

url#

‘SerializerMethodField(…)’

name#

‘SerializerMethodField(…)’

type#

‘SerializerMethodField(…)’

given_name#

‘SerializerMethodField(…)’

family_name#

‘SerializerMethodField(…)’

name_identifiers#

‘NameIdentifierSerializer(…)’

affiliation#

‘SerializerMethodField(…)’

roles#

‘RoleSerializer(…)’

class Meta#
list_serializer_class#

None

static is_organization(credit) → bool#

Say whether the credited contributor is an organization, without a query.

is_hidden(credit) → bool#

Say whether the people list leaves out the credited contributor.

get_uuid(credit) → str | None#

Give the contributor’s short identifier, or nothing for a hidden account.

get_url(credit) → str | None#

Give the contributor’s address in the API, or nothing for a hidden account.

get_name(credit) → str#

Give an organization’s name, or a person’s as “Family, Given”.

get_type(credit) → str#

Say whether the credit is for a person or an organization.

get_given_name(credit) → str | None#

Give a person’s given name, and nothing for an organization or where unset.

get_family_name(credit) → str | None#

Give a person’s family name, and nothing for an organization or where unset.

get_affiliation(credit) → dict | None#

Give the organization recorded on the credit, or nothing when it records none.

class LicenseSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

The licence a dataset is published under.

Initialization

name#

‘CharField(…)’

url#

‘CharField(…)’

class RecordSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.CreatorCreditMixin, rest_framework.serializers.ModelSerializer

Serializer for a project, dataset, sample or measurement.

Adds what every record carries: its address, identifier and dates of change, and the five kinds of metadata, which are read-only.

Attributes: metadata_fields: The metadata every record carries. parents: The relations to load with the record, so a list costs no query per record.

Initialization

metadata_fields#

(‘descriptions’, ‘dates’, ‘identifiers’, ‘keywords’, ‘contributors’)

parents: tuple[str, ...]#

()

url#

‘RecordURLField(…)’

html_url#

‘PortalPageField(…)’

descriptions#

‘DescriptionSerializer(…)’

dates#

‘DateSerializer(…)’

identifiers#

‘IdentifierSerializer(…)’

keywords#

‘KeywordSerializer(…)’

contributors#

‘ContributionSerializer(…)’

class Meta#
list_serializer_class#

None

Load the parents and metadata a serialized record reads.

Args: queryset: The records about to be serialized.

Returns: The queryset with its parents selected and its metadata prefetched.

class ProjectSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.RecordSerializer

A project with its owner and its metadata.

Initialization

parents#

(‘owner’,)

owner#

‘RecordReferenceField(…)’

class Meta#

Bases: fairdm.api.serializers.RecordSerializer

model#

None

fields#

None

read_only_fields#

[‘image’]

class DatasetSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.RecordSerializer

A dataset with its project, its licence and its metadata.

Initialization

parents#

(‘project’, ‘license’)

project#

‘RecordReferenceField(…)’

license#

‘LicenseSerializer(…)’

class Meta#

Bases: fairdm.api.serializers.RecordSerializer

model#

None

fields#

None

read_only_fields#

[‘image’, ‘published’]

class BaseSampleSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.RecordSerializer

Base DRF serializer for all Sample subtypes.

All auto-generated serializers for registered :class:~fairdm.core.sample.models.Sample subclasses inherit from this class. When a portal developer provides a custom serializer_class via the registry config it MUST subclass this class; otherwise :func:generate_viewset raises :exc:~django.core.exceptions.ImproperlyConfigured.

Attributes: common_fields: The fields every sample carries, whatever its type declares.

Initialization

common_fields#

(‘url’, ‘html_url’, ‘uuid’, ‘name’, ‘local_id’, ‘status’, ‘dataset’, ‘location’, ‘location_uncertain…

parents#

(‘dataset’,)

dataset#

‘RecordReferenceField(…)’

location#

‘GeoJSONPointField(…)’

class Meta#

Bases: fairdm.api.serializers.RecordSerializer

model#

None

fields#

None

read_only_fields#

[‘location’, ‘location_elevation’, ‘location_uncertainty’]

class BaseMeasurementSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.RecordSerializer

Base DRF serializer for all Measurement subtypes.

All auto-generated serializers for registered :class:~fairdm.core.measurement.models.Measurement subclasses inherit from this class. When a portal developer provides a custom serializer_class via the registry config it MUST subclass this class; otherwise :func:generate_viewset raises :exc:~django.core.exceptions.ImproperlyConfigured.

Attributes: common_fields: The fields every measurement carries, whatever its type declares.

Initialization

common_fields#

(‘url’, ‘html_url’, ‘uuid’, ‘name’, ‘sample’, ‘dataset’, ‘location’, ‘location_uncertainty’, ‘added’…

parents#

(‘sample’, ‘dataset’)

sample#

‘RecordReferenceField(…)’

dataset#

‘RecordReferenceField(…)’

location#

‘GeoJSONPointField(…)’

class Meta#

Bases: fairdm.api.serializers.RecordSerializer

model#

None

fields#

None

read_only_fields#

[‘location’, ‘location_elevation’, ‘location_uncertainty’]

class ContributorIdentifierSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

An identifier of a contributor, such as an ORCID iD, its type’s address and its own.

Initialization

type#

‘CharField(…)’

value#

‘CharField(…)’

‘CharField(…)’

class ContributorRecordsMixin(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

Gives a contributor the addresses of the project and dataset lists narrowed to them.

Each address is absolute when the request is known and the path alone when it is not. The lists it points to hold the public records the contributor is credited on.

Initialization

projects#

‘SerializerMethodField(…)’

datasets#

‘SerializerMethodField(…)’

records_address(route: str, contributor) → str#

Give the address of a record list narrowed to a contributor.

Args: route: The name of the list route. contributor: The person or organization the list is narrowed to.

Returns: The list’s address with the contributor’s short identifier as a query.

get_projects(contributor) → str#

Give the address of the projects the contributor is credited on.

get_datasets(contributor) → str#

Give the address of the datasets the contributor is credited on.

class PersonListSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.ModelSerializer

A person as the people list shows them: who they are and where they mainly belong.

Nothing about the account behind a person is returned: no email address, credential, flag or sign-in date.

Initialization

url#

‘RecordURLField(…)’

html_url#

‘PortalPageField(…)’

given_name#

‘CharField(…)’

family_name#

‘CharField(…)’

identifiers#

‘ContributorIdentifierSerializer(…)’

primary_affiliation#

‘SerializerMethodField(…)’

class Meta#
model#

None

fields: tuple[str, ...]#

(‘url’, ‘html_url’, ‘uuid’, ‘name’, ‘given_name’, ‘family_name’, ‘identifiers’, ‘primary_affiliation…

read_only_fields#

None

get_primary_affiliation(person) → dict | None#

Refer to the organization of the person’s primary affiliation, when it is current.

A pending or ended affiliation gives none.

class AffiliationTypeField(**kwargs)#

Bases: rest_framework.serializers.Field

The level of an affiliation, given as the lower-case name of its membership type.

Initialization

Read the affiliation’s type and never write it.

Args: **kwargs: Passed to Field.

to_representation(value) → str#

Give the name of the level.

Args: value: The stored membership type.

Returns: member, admin or owner.

class AffiliationSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A verified affiliation of a person: the organization, the kind, and the dates.

The dates are given as they were recorded, as a year, a month or a day, and are null when none was recorded.

Initialization

organization#

‘OrganizationReferenceSerializer(…)’

type#

‘AffiliationTypeField(…)’

start#

‘SerializerMethodField(…)’

end#

‘SerializerMethodField(…)’

is_primary#

‘BooleanField(…)’

get_start(affiliation) → str | None#

Give when the affiliation began, or nothing when it is not recorded.

get_end(affiliation) → str | None#

Give when the affiliation ended, or nothing when it has not.

class PersonSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.ContributorRecordsMixin, fairdm.api.serializers.PersonListSerializer

A single person, as far as their public profile page shows.

It carries every field of a list entry together with the person’s other names, profile, links, languages, image and verified affiliations, and the addresses of the projects and datasets they are credited on. Nothing about the account behind a person is returned.

Initialization

alternative_names#

‘ListField(…)’

image#

‘ImageField(…)’

‘SerializerMethodField(…)’

languages#

‘SerializerMethodField(…)’

affiliations#

‘SerializerMethodField(…)’

class Meta#

Bases: fairdm.api.serializers.PersonListSerializer

fields#

()

read_only_fields#

None

List the web addresses the profile page draws.

get_languages(person) → list[str]#

Name the person’s languages in the active language.

get_affiliations(person) → list[dict]#

List the verified affiliations, the current ones first and then the past ones.

class OrganizationListSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.ModelSerializer

An organization as the organizations list shows it.

The type and the country are given as the codes that are stored, which are the values the lists filter by.

Initialization

url#

‘RecordURLField(…)’

html_url#

‘PortalPageField(…)’

identifiers#

‘ContributorIdentifierSerializer(…)’

country#

‘SerializerMethodField(…)’

location#

‘GeoJSONPointField(…)’

class Meta#
model#

None

fields: tuple[str, ...]#

(‘url’, ‘html_url’, ‘uuid’, ‘name’, ‘type’, ‘country’, ‘location’, ‘identifiers’)

read_only_fields#

None

get_country(organization) → str | None#

Give the two-letter code of the country, or nothing when none is set.

class PersonReferenceSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A person named by their short identifier, their address in the API and their name.

Initialization

uuid#

‘CharField(…)’

url#

‘RecordURLField(…)’

name#

‘CharField(…)’

class MemberSerializer(instance=None, data=empty, **kwargs)#

Bases: rest_framework.serializers.Serializer

A person who belongs to an organization, and the kind of affiliation they hold.

Initialization

person#

‘PersonReferenceSerializer(…)’

type#

‘AffiliationTypeField(…)’

class OrganizationSerializer(instance=None, data=empty, **kwargs)#

Bases: fairdm.api.serializers.ContributorRecordsMixin, fairdm.api.serializers.OrganizationListSerializer

A single organization, as far as its public profile page shows.

It carries every field of a list entry together with the organization’s other names, profile, city, links, image, the organization it is part of, the organizations that are part of it, its current members, and the addresses of the projects and datasets it is credited on.

Initialization

alternative_names#

‘ListField(…)’

image#

‘ImageField(…)’

‘SerializerMethodField(…)’

parent_organization#

‘OrganizationReferenceSerializer(…)’

sub_organizations#

‘OrganizationReferenceSerializer(…)’

members#

‘SerializerMethodField(…)’

class Meta#

Bases: fairdm.api.serializers.OrganizationListSerializer

fields#

()

read_only_fields#

None

List the web addresses the profile page draws.

get_members(organization) → list[dict]#

List the verified members whose affiliation has not ended.

The people who run the organization come first, each group by name. A superuser and the anonymous account are left out, as the people list leaves them out.

class BaseSerializerMixin#

Mixin that adds a url hyperlinked field to a serializer that sets its view_name.

The url field uses lookup_field="uuid" to match the viewset’s lookup.

url#

‘HyperlinkedIdentityField(…)’