Skip to main content

django-sensorthings is a Django application for handling ogc sensorthings data.

Project description

A Django application for handling OGC SensorThings API data. Provides ready-to-use Django models, REST API views, serializers, and sensible default configurations for building SensorThings- and TIGER geocoding-compatible services.

Requirements

  • Python ≥ 3.12

  • Django ≥ 6.0

Runtime dependencies (installed automatically):

  • django-cors-headers ≥ 4

  • django-extensions ≥ 4

  • django-filter ≥ 25

  • djangorestframework ≥ 3.16

  • djangorestframework-gis ≥ 1.2

  • djangorestframework-simplejwt ≥ 5.5

  • drf-spectacular ≥ 0.28

  • drf-spectacular-sidecar ≥ 2026.3

Installation

Install from PyPI:

pip install django-sensorthings

Or via uv:

uv add django-sensorthings

Quick Start

  1. Add the app and its dependencies to INSTALLED_APPS:

    You can use the pre-defined lists from sensorthings.defaults, or add the entries by hand.

     # settings.py
    from sensorthings import defaults as ST
    
    INSTALLED_APPS = [
        *ST.INSTALLED_APPS_OPTIONS["core"],
        *ST.INSTALLED_APPS_OPTIONS["swagger"],
        *ST.INSTALLED_APPS_OPTIONS["gis"],
        "sensorthings",
        # ... your own apps
    ]
    
    # or if you want to use the default settings
    INSTALLED_APPS = ST.INSTALLED_APPS
  2. Include the URL configuration in your project’s root urls.py:

      # urls.py
      from django.urls import path, include
    
      urlpatterns = [
          path("api/", include("sensorthings.routes.api")),
          path("api/", include("sensorthings.routes.jwt")),
          path("api/", include("sensorthings.routes.swagger")),
          # ...
      ]
    # or if you want to use the default settings
    from sensorthings import defaults as ST
    urlpatterns = [
        path("api/", include("sensorthings.urls")),
        # ...
    ]

    This will mount the following URL groups:

    Prefix

    Description

    /api/jwt/

    JWT authentication endpoints

    /api/sensorthings/

    SensorThings REST API (DRF router)

    /api/swagger/

    Swagger UI & OpenAPI schema

  3. Apply migrations:

    python manage.py migrate
  4. Run the development server:

    python manage.py runserver

    Visit http://localhost:8000/api/swagger/ to explore the auto-generated Swagger documentation.

Defaults

sensorthings.defaults provides ready-made configuration dictionaries that you can import into your project’s settings.py. Each setting can be overridden as needed.

INSTALLED_APPS_OPTIONS

A dictionary of app lists grouped by category:

from sensorthings.defaults import INSTALLED_APPS_OPTIONS
  • INSTALLED_APPS_OPTIONS["core"] — Core Django apps, CORS, extensions, DRF, django-filter, and SimpleJWT.

  • INSTALLED_APPS_OPTIONS["gis"]django.contrib.gis and rest_framework_gis.

  • INSTALLED_APPS_OPTIONS["swagger"]drf_spectacular and its sidecar.

DATABASE_OPTIONS

Pre-built DATABASES["default"] engine entries:

from sensorthings.defaults import DATABASE_OPTIONS

DATABASES = {
    "default": {
        **DATABASE_OPTIONS["spatialite"],
        "NAME": "mydb",
        "USER": "myuser",
        "PASSWORD": "secret",
        "HOST": "localhost",
        "PORT": "5432",
    }
}

Available keys:

Key

Engine

spatialite

django.contrib.gis.db.backends.spatialite

postgis

django.contrib.gis.db.backends.postgis

postgres

django.db.backends.postgresql

REST_FRAMEWORK

Default DRF settings including pagination, filtering, schema, and authentication classes:

from sensorthings.defaults import REST_FRAMEWORK

Key settings:

  • PAGE_SIZE: 1

  • DEFAULT_SCHEMA_CLASS: drf_spectacular.openapi.AutoSchema

  • DEFAULT_PAGINATION_CLASS: LimitOffsetPagination

  • DEFAULT_FILTER_BACKENDS: DjangoFilterBackend

  • DEFAULT_AUTHENTICATION_CLASSES: JWT, Basic, Token, and Session authentication.

SIMPLE_JWT

SimpleJWT configuration:

from sensorthings.defaults import SIMPLE_JWT

Notable defaults:

  • ACCESS_TOKEN_LIFETIME: 24 hours

  • REFRESH_TOKEN_LIFETIME: 2 days

  • AUTH_HEADER_TYPES: ("JWT",)

  • ALGORITHM: HS256

SPECTACULAR_SETTINGS

drf-spectacular OpenAPI configuration:

from sensorthings.defaults import SPECTACULAR_SETTINGS
  • OAS_VERSION: 3.0.3

  • TITLE: Configurable via the SENSORTHINGS_SWAGGER_TITLE env variable (default: "Sensorthings").

  • VERSION: Configurable via the API_VERSION env variable (default: "1.0.0").

  • Swagger UI served via the drf_spectacular_sidecar.

SWAGGER_SETTINGS

from sensorthings.defaults import SWAGGER_SETTINGS
  • LOGIN_URL: "rest_framework:login"

  • LOGOUT_URL: "rest_framework:logout"

MIDDLEWARE

A default middleware stack including CORS support:

from sensorthings.defaults import MIDDLEWARE

Includes SecurityMiddleware, SessionMiddleware, CorsMiddleware, CommonMiddleware, CsrfViewMiddleware, AuthenticationMiddleware, MessageMiddleware, and XFrameOptionsMiddleware.

SENSORTHINGS_ENABLE_PUBLIC_PRIVATE / SENSORTHINGS_ENABLE_OWNER

Boolean flags that control queryset visibility in MetaViewset:

SENSORTHINGS_ENABLE_PUBLIC_PRIVATE = True  # default
SENSORTHINGS_ENABLE_OWNER = True           # default

See the Views section for details on how these flags affect query filtering.

Models

All models are defined in sensorthings.models and inherit from the abstract MetaModel base class. Models are mapped to existing database tables using db_table in the Meta class and are unmanaged by default (no migrations will alter their schema).

SensorThings Core Models

These models implement the OGC SensorThings API data model:

Model

Table

Description

Things

things

An object of the physical or virtual world.

Locations

locations

The last known location of a Thing.

HistLocations

hist_locations

Historical locations of a Thing.

Sensors

sensors

Instruments that observe a property.

ObservedProperties

observed_properties

The phenomenon being observed.

Datastreams

datastreams

Groups observations from a sensor on a thing.

Observations

observations

Individual measurement results.

Features

features

Features of interest for observations.

FeatureTypes

feature_types

Classification of features.

Samplers

samplers

Devices or entities performing sampling.

Samplings

samplings

Sampling events with location and time range.

SamplingProcedures

sampling_procedures

Procedures used during sampling.

PreparationProcedures

preparation_procedures

Procedures for preparing samples.

PreparationSteps

preparation_steps

Individual steps in a preparation procedure.

RelationRoles

relation_roles

Defines roles for entity relationships.

Association / Join Tables

Model

Table

ThingsLocations

things_locations

LocationsHistLocations

locations_hist_locations

DatastreamsObservedProperties

datastreams_observed_properties

DatastreamsFeaturesUltimate

datastreams_features_ultimate

FeaturesFeatureTypes

features_feature_types

SamplerSamplingProcedure

sampler_sampling_procedure

Relation Models

Model

Table

RelatedDatastreams

related_datastreams

RelatedFeatures

related_features

RelatedObservations

related_observations

RelatedThings

related_things

TIGER / Geocoding Models

Provides models for US TIGER/Line geocoding tables:

Addr, Addrfeat, Bg, County, CountyLookup, CountysubLookup, Cousub, Edges, Faces, Featnames, Place, PlaceLookup, State, StateLookup, Tabblock, Tabblock20, Tract, Zcta5, ZipLookup, ZipLookupAll, ZipLookupBase, ZipState, ZipStateLoc, and various lookup tables (DirectionLookup, SecondaryUnitLookup, StreetTypeLookup, LoaderLookuptables, LoaderPlatform, LoaderVariables, GeocodeSettings, GeocodeSettingsDefault).

Utility Models

  • Databasechangelog / Databasechangeloglock — Liquibase migration tracking tables.

  • Layer / Topology — PostGIS topology support tables.

  • PagcGaz, PagcLex, PagcRules — PAGC geocoder lexicon tables.

Routes

URL routing is defined in sensorthings.urls and split into three route modules under sensorthings.routes:

sensorthings.urls

The main URL configuration that you include in your project:

from django.urls import path, include

urlpatterns = [
    path("api/", include("sensorthings.urls")),
]

This mounts:

sensorthings.routes.swagger

URL

View

swagger/

SpectacularSwaggerView — interactive docs

schema/

SpectacularJSONAPIView — OpenAPI schema

sensorthings.routes.jwt

URL

View

jwt/

TokenObtainPairView — obtain JWT pair

jwt/verify/

TokenVerifyView — verify a token

jwt/refresh/

TokenRefreshView — refresh a token

sensorthings.routes.api

All SensorThings and geocoding entity endpoints are registered with the DRF DefaultRouter and are mounted under the sensorthings/ prefix. Each model has a corresponding endpoint:

sensorthings/Things/
sensorthings/Locations/
sensorthings/Observations/
sensorthings/Datastreams/
sensorthings/Sensors/
sensorthings/Features/
sensorthings/ObservedProperties/
...

Each endpoint supports standard REST operations (list, create, retrieve, update, partial update, destroy) depending on the viewset permissions.

Views

All views are defined in sensorthings.views and inherit from the MetaViewset base class.

MetaViewset

from rest_framework import permissions
from rest_framework.viewsets import ModelViewSet
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend

class MetaViewset(ModelViewSet):
    serializer_class = None
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [
        DjangoFilterBackend,
        filters.SearchFilter,
        filters.OrderingFilter,
    ]

Key behaviour:

  • Permission: IsAuthenticatedOrReadOnly — anonymous users get read-only access, authenticated users can write.

  • Filter backends: DjangoFilterBackend (field-level filtering), SearchFilter (text search), and OrderingFilter (sort results).

  • Queryset: Controlled by two Django settings:

    • SENSORTHINGS_ENABLE_PUBLIC_PRIVATE + SENSORTHINGS_ENABLE_OWNER — returns objects owned by the current user or public, excluding private.

    • SENSORTHINGS_ENABLE_PUBLIC_PRIVATE only — returns public objects, excluding private.

    • SENSORTHINGS_ENABLE_OWNER only — returns objects owned by the current user.

    • Both False — returns all objects.

set_filterset_fields_exclude

A helper function that auto-generates filterset_fields and search_fields for a viewset by inspecting the model’s fields and excluding types that do not support text lookups:

from sensorthings.views import set_filterset_fields_exclude

class MyViewset(MetaViewset):
    serializer_class = MySerializer
    filterset_fields = set_filterset_fields_exclude(serializer_class)
    search_fields = filterset_fields + ["id"]

Excluded field types: JSONField, GeometryField, PointField, MultiPointField, PolygonField, MultiPolygonField, LineStringField, MultiLineStringField, ForeignKey, OneToOneField, ManyToManyField, ManyToManyRel, ManyToOneRel, GenericForeignKey, FileField, and CompositePrimaryKey.

Entity Viewsets

Every model has a corresponding viewset that overrides serializer_class. Some viewsets also set filterset_fields and search_fields automatically:

class AddrViewset(MetaViewset):
    serializer_class = serializers.AddrSerializer
    filterset_fields = set_filterset_fields_exclude(serializer_class)
    search_fields = filterset_fields + ["id"]

class ThingsViewset(MetaViewset):
    serializer_class = serializers.ThingsSerializer

# ... one viewset per model

To customise the queryset or permissions, subclass the relevant viewset:

from sensorthings.views import ThingsViewset

class MyThingsViewset(ThingsViewset):
    def get_queryset(self):
        return self.serializer_class.Meta.model.objects.filter(
            properties__project="demo"
        )

Serializers

All serializers live in sensorthings.serializers and inherit from the MetaModelSerializer base class.

MetaModelSerializer

from rest_framework import serializers

class MetaModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = None

Each entity serializer sets its Meta.model to the corresponding model and exposes all fields:

class ThingsSerializer(MetaModelSerializer):
    class Meta:
        model = models.Things
        fields = "__all__"

class SensorsSerializer(MetaModelSerializer):
    class Meta:
        model = models.Sensors
        fields = "__all__"

# ... one serializer per model

To add computed fields or nested representations, subclass the serializer:

from sensorthings.serializers import DatastreamsSerializer

class DetailedDatastreamsSerializer(DatastreamsSerializer):
    sensor_name = serializers.CharField(source="sensor.name", read_only=True)

    class Meta(DatastreamsSerializer.Meta):
        fields = "__all__"

Admin

All models are automatically registered with the Django admin. Each admin class dynamically lists all model fields in list_display:

from django.contrib import admin
from django.apps import apps

app_models = apps.get_app_config("sensorthings").get_models()

for model in app_models:
    class DynamicAdmin(admin.ModelAdmin):
        list_display = [field.name for field in model._meta.fields]

    admin.site.register(model, DynamicAdmin)

Access the admin at /admin/ after creating a superuser:

python manage.py createsuperuser

Full Example Project

Below is a minimal settings.py for a new Django project using django-sensorthings:

# settings.py
from pathlib import Path
from sensorthings import defaults as ST

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = "django-insecure-ikb3ow6j856g7tue7a1#sy)*(onocx-#@kh)e7xv6hi8vv=7b1"

DEBUG = True

ALLOWED_HOSTS = ["*"]

INSTALLED_APPS = ST.INSTALLED_APPS

MIDDLEWARE = ST.MIDDLEWARE

ROOT_URLCONF = "interface.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "interface.wsgi.application"

DATABASES = {
    "default": {"NAME": BASE_DIR / "db.sqlite3", **ST.DATABASE_OPTIONS["spatialite"]}
}

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]


LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True

STATIC_URL = "static/"

REST_FRAMEWORK = ST.REST_FRAMEWORK

SIMPLE_JWT = ST.SIMPLE_JWT

SPECTACULAR_SETTINGS = ST.SPECTACULAR_SETTINGS

SWAGGER_SETTINGS = ST.SWAGGER_SETTINGS

And the corresponding urls.py:

# urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", include("sensorthings.urls")),
]

Configuration

Environment Variables

Variable

Description

Default

SENSORTHINGS_SWAGGER_TITLE

Title shown in the Swagger UI

Sensorthings

API_VERSION

API version in the OpenAPI schema

1.0.0

Django Settings

Add these to your settings.py to control viewset queryset behaviour:

Setting

Description

Default

SENSORTHINGS_ENABLE_PUBLIC_PRIVATE

Filter by is_public / is_private

True

SENSORTHINGS_ENABLE_OWNER

Filter by has_owner (current user)

True

When both are True, the queryset returns objects owned by the current user or marked as public, while excluding private objects. Set either to False to disable that filter dimension.

License

Distributed under the GPL-3.0 license. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_sensorthings-1.0.0.tar.gz (48.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_sensorthings-1.0.0-py3-none-any.whl (45.0 kB view details)

Uploaded Python 3

File details

Details for the file django_sensorthings-1.0.0.tar.gz.

File metadata

  • Download URL: django_sensorthings-1.0.0.tar.gz
  • Upload date:
  • Size: 48.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_sensorthings-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e8e7af385e507ee43d49569523107317a34685f1dea8f999c67927bb3b1752d0
MD5 882629a5de4d6e90044d97c6ec219923
BLAKE2b-256 b0b8f7a4c7f71aade48a76ce1a20c2aea991e70bbcba46fd2b8c2ab07775a95e

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_sensorthings-1.0.0.tar.gz:

Publisher: release.yaml on Groupeffect/django-sensorthings

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_sensorthings-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_sensorthings-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d3c386b519e116f60635432a166194a13f2b5d3d4076431725ddf1557137424b
MD5 8fe1f15f5a0b1ec3abd6e6c483ed8b19
BLAKE2b-256 2fdb2cd8cd6c24f6f63885e734703b078544c2d1df49f37db65a2e83e0aa209c

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_sensorthings-1.0.0-py3-none-any.whl:

Publisher: release.yaml on Groupeffect/django-sensorthings

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page