Skip to main content

yesterdays-panoramax

CI PyPI Python License: AGPL v3

A Django app that publishes a Yesterdays historical image archive to the Panoramax federation, by serving a Panoramax-compatible STAC API.

Drop it into an existing installation: one dependency, one line in INSTALLED_APPS, one URL include, one migration. It adds no column to the images tables and changes no existing behaviour.

pip install yesterdays-panoramax

What it does

Panoramax is not a push protocol. A central meta-catalogue (api.panoramax.xyz) runs a harvester that crawls each registered instance's STAC API on a schedule and copies the metadata into a shared, searchable database. The pictures never move — they stay on the instance that hosts them.

This package makes a Yesterdays instance one of those crawlable instances. Your georeferenced historical photographs become discoverable alongside the rest of the federation, and every item links back to its record on your site.

It maps:

Yesterdays Panoramax / STAC
images.Collection STAC Collection ("sequence")
images.Image STAC Item ("picture")
latest Georeference.point item geometry
Georeference.direction view:azimuth
Georeference.confidence quality:horizontal_accuracy
Image.edtf_date datetime + start_datetime/end_datetime
display_permalink / thumbnail hd / sd / thumb assets

Quick start

# settings.py
INSTALLED_APPS = [
    ...,
    "yesterdays_panoramax",
]

PANORAMAX_ENABLED = True

# images.License names -> SPDX identifiers.
PANORAMAX_LICENSE_ALLOWLIST = {
    "No known copyright restrictions": "CC0-1.0",
    "CC BY-SA 4.0": "CC-BY-SA-4.0",
}

PANORAMAX_INSTANCE_NAME = "Yesterdays"
PANORAMAX_CONTACT_EMAIL = "you@example.org"

# Set once. Never change it. See docs/configuration.md.
PANORAMAX_UUID_NAMESPACE = "6f3d6b1a-6b0e-5a3f-9c8d-0f1c2a4b8e7d"
# urls.py -- the /api/ prefix is not optional, see below
urlpatterns = [
    ...,
    path("api/", include("yesterdays_panoramax.urls", namespace="panoramax")),
]
manage.py migrate panoramax
manage.py panoramax_backfill

[!IMPORTANT] The harvester builds its requests as {instance_url}/api/collections with the prefix hardcoded, so the app must be mounted at /api/. If your project already serves something there — Yesterdays serves its REST API at /api/v2/ — include this app after those routes.

Publication is opt-in twice over: PANORAMAX_ENABLED, and a licence allowlist that starts empty. An instance with the flag on and no allowlist publishes nothing. That is deliberate — Panoramax's federation policy expects open licensing, and only a human can say which of an archive's licences qualify.

Ruling on individual photographs

Licences and visibility flags cannot express a judgement about one particular picture — a portrait whose subject asked not to have it republished, a scan whose provenance turned out to be murky. So decisions can also be made per image:

from yesterdays_panoramax import api

api.exclude_image(image, reason="Depicted person objected", by=request.user)

Or, for archives whose rights are settled picture by picture rather than licence by licence, invert the default so nothing is published until it is approved:

PANORAMAX_IMAGE_POLICY = "opt-in"

An exclusion is absolute; an approval is not an override — an approved image still has to satisfy the licence, visibility, date and georeference rules. The feature is inert until used. See per-image control.

Joining the federation

Serving the API is only half of it. To actually be harvested, open an issue on panoramax/server/meta-catalog asking to be added; an administrator runs stac-harvester add-instance <name> --url https://your.instance. There is no self-service endpoint.

Before you do, two questions the code cannot answer for you:

  • Licensing. The federation expects Licence Ouverte 2.0 or CC-BY-SA 4.0, and /api/configuration advertises one instance-wide licence.
  • Fit. Panoramax catalogues contemporary field photography for OpenStreetMap mapping. Historical photographs with crowd-estimated positions are a different kind of data. There is precedent — the OSM-FR instance carries items back to 1904 — but it is worth raising with the Panoramax community before publishing at scale.

Documentation

Installation Adding it to a Yesterdays project
Configuration Every setting, and what it does
How it works The federation model and the harvester contract
Data mapping What gets published, and the judgement calls
Per-image control Holding back, or approving, one photograph
Endpoints The API surface
Operations Backfilling, withdrawal, troubleshooting
Host contract What the package needs from images
Releasing Cutting a version

Requirements

  • Python 3.11+
  • Django 4.2+
  • PostgreSQL with PostGIS (the adapter aggregates extents, filters spatially, and builds vector tiles with ST_AsMVT)
  • A Yesterdays installation providing the images app — see host contract

Development

pip install -e ".[test]"
./manage.py test tests

The suite runs against a stubbed host app in tests/images/, so you do not need a full Yesterdays deployment. It needs a PostGIS database; connection details come from the usual PG* environment variables.

Licence

AGPL-3.0-or-later, matching Yesterdays. See LICENSE.

Download files

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

Source Distribution

yesterdays_panoramax-0.1.0.tar.gz (72.5 kB view details)

Uploaded Source

Built Distribution

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

yesterdays_panoramax-0.1.0-py3-none-any.whl (58.6 kB view details)

Uploaded Python 3

File details

Details for the file yesterdays_panoramax-0.1.0.tar.gz.

File metadata

  • Download URL: yesterdays_panoramax-0.1.0.tar.gz
  • Upload date:
  • Size: 72.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for yesterdays_panoramax-0.1.0.tar.gz
Algorithm Hash digest
SHA256 99ef97ee0deb9a00da171e9626326957b4df7fc43bacfcb5b1cc09aace82a1f0
MD5 f7baa2422534f75069045985d73b4a17
BLAKE2b-256 546e32a9adb8a12fe63041f1148228d3ac9dce74c9812aea23f4d14908c2bb01

See more details on using hashes here.

Provenance

The following attestation bundles were made for yesterdays_panoramax-0.1.0.tar.gz:

Publisher: publish.yml on openhistorymap/yesterdays-panoramax

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

File details

Details for the file yesterdays_panoramax-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for yesterdays_panoramax-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3d22e9ab1aa80bf0daadc528ebf80e322dabe369d88841a79de1b55bebfc2f4d
MD5 7cb0f5eb9848086177aa5f1c4cb87774
BLAKE2b-256 ecbcfff5dc96658a61fc28a214f48a370df0b5fa98bfa7e683de9f2841bfdb4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for yesterdays_panoramax-0.1.0-py3-none-any.whl:

Publisher: publish.yml on openhistorymap/yesterdays-panoramax

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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page