Skip to content

Collections

Each model registered with OAPIF is served as a collection of features: its rows are the features, its geometry field their geometry, and its other fields their properties.

Registering models

register_collection takes a model, or a list of models, and the class that serves them, which defaults to OapifCollection:

from django_oapif import OAPIF, AnonReadOnlyCollection

from .models import Building, Parcel, Road

oapif = OAPIF()

oapif.register_collection(Building)
oapif.register_collection([Parcel, Road], AnonReadOnlyCollection)

To configure a collection, subclass OapifCollection, or one of the classes of permissions, and register it with the register decorator:

from django_oapif import OapifCollection

@oapif.register(Building)
class BuildingCollection(OapifCollection):
    id = "buildings"
    title = "Buildings"
    description = "The buildings of the city"
    fields = ("name", "height", "roof")
    readonly_fields = ("height",)
    ordering = ("name",)

A model can be registered more than once, as long as each collection has an id of its own: to serve a subset of its fields, for instance.

Options

Attribute Default Description
id the model label in lower case, my_app.building The identifier of the collection in the URLs: /collections/{id}/items.
title the model label, my_app.Building The title of the collection.
description none The description of the collection.
geometry_field the geometry field of the model The field of the feature geometries. None serves the collection without geometry.
fields every field of the model, but the geometry and reverse relations The fields served as properties, in this order.
readonly_fields none Fields that are served, but not accepted in writes.
exclude none Fields that are not served.
ordering the model Meta.ordering, then the primary key The order of the features.
linearization_tolerance none, 32 segments a quarter of a circle The largest distance between an arc and its segments when curves are linearized, in the unit of the storage CRS.

A model with several geometry fields has to name one in geometry_field, and cannot be registered otherwise. The fields pages describe how each kind of field is served.

The primary key completes the ordering of the model so that pages of features never overlap, nor skip one: an ordering set on the collection is taken as it is, and should end with a unique field as well.

Hooks

The methods of OapifCollection can be overridden to adapt a collection to each request, the way those of Django's ModelAdmin are:

Method Returns
get_queryset(request) The rows it serves, changes and deletes, computes its extent from, and that foreign keys to it may reference.
get_fields(request, obj=None) The fields served as properties, fields by default.
get_exclude(request, obj=None) The fields not served, exclude by default.
get_readonly_fields(request, obj=None) The fields not accepted in writes: readonly_fields, generated fields and files.
get_ordering(request) The order of the features.
get_queryables(request) The fields the features can be filtered on.
save_model(request, obj, change) Saves a created or changed row.
delete_model(request, obj) Deletes a row.
has_view_permission(request, obj=None), and the add, change and delete ones See permissions.
storage_crs(), supported_crs() See coordinate reference systems.

For instance, to serve each user their own features only, and to record who created one:

@oapif.register(Observation)
class ObservationCollection(OapifCollection):
    readonly_fields = ("author",)

    def get_queryset(self, request):
        return super().get_queryset(request).filter(author=request.user)

    def save_model(self, request, obj, change):
        if not change:
            obj.author = request.user
        super().save_model(request, obj, change)

The API reference lists them all.