Info and manifest documents¶
Beyond profile URLs, djiiif can build the two JSON documents that IIIF viewers
consume: an Image API info.json and a Presentation API manifest.
Unlike the profile URLs, these read the image’s real pixel dimensions from
storage.
URL vs. document
iiif.info returns the URL of an external info.json (served by your image
server). iiif.info_document returns the document itself (a dict), built
locally. They are complementary — .info is unchanged and always available.
Metadata URLs¶
Two lightweight, I/O-free URL attributes:
>>> photo.image.iiif.info
'https://images.example.org/uploads%2Fsunset.jpg/info.json'
>>> photo.image.iiif.identifier # host + identifier, no IIIF suffix
'https://images.example.org/uploads%2Fsunset.jpg'
iiif.identifier is the plain {host}/{identifier} base URL — handy for handing
an image to a viewer like OpenSeadragon that takes just the IIIF identifier.
info.json document¶
iiif.info_document assembles a spec-valid Image API document from the image’s
own dimensions, so a Django view can serve info.json without a separate image
server:
from django.http import JsonResponse
def image_info(request, pk):
photo = Photo.objects.get(pk=pk)
return JsonResponse(photo.image.iiif.info_document)
>>> photo.image.iiif.info_document
{'@context': 'http://iiif.io/api/image/3/context.json',
'id': 'https://images.example.org/uploads%2Fsunset.jpg',
'type': 'ImageService3',
'protocol': 'http://iiif.io/api/image',
'profile': 'level2',
'width': 4000,
'height': 3000}
Because it needs real dimensions, accessing .info_document reads the image from
storage. For an empty/unset field it returns None.
Manifest document¶
iiif.manifest returns a minimal single-image
Presentation 3.0 manifest — one image on
one canvas — ready to hand to Mirador, the Universal Viewer, or OpenSeadragon:
def image_manifest(request, pk):
photo = Photo.objects.get(pk=pk)
return JsonResponse(photo.image.iiif.manifest)
The label defaults to the file’s base name; like info_document it reads
dimensions from storage and returns None for an empty field. To enrich the
manifest with descriptive metadata, multiple images, or collections, see
Richer manifests & collections.
Choosing the API version and compliance level¶
Two settings control the generated document shapes:
Setting |
Default |
Effect |
|---|---|---|
|
|
|
|
|
The compliance level advertised in |
The manifest is always Presentation 3.0; only its embedded image service
follows IIIF_IMAGE_API_VERSION. An unknown version raises
ImproperlyConfigured.
IIIF_IMAGE_API_VERSION = 2
IIIF_COMPLIANCE_LEVEL = "level1"
Enriching info.json¶
The default info.json is deliberately minimal. Set IIIF_INFO to advertise
the optional Image API properties your image server actually supports — preferred
sizes, tiles for deep-zoom clients, server size limits, a rights URI, and
v3 capability lists:
IIIF_INFO = {
"tiles": [{"width": 512, "scaleFactors": [1, 2, 4, 8]}],
"max_width": 5000,
"rights": "http://creativecommons.org/licenses/by/4.0/",
"preferred_formats": ["webp", "jpg"],
}
Keys may be snake_case (above) or spec camelCase (maxWidth,
preferredFormats, …) — supply each property once; giving both spellings raises
ImproperlyConfigured. For per-image values, use a callable — it receives the
IIIFFieldFile on the model path and the decoded storage name (a str) on
the view path:
def info_extras(parent):
w, h = parent.width, parent.height
return {"sizes": [{"width": w // f, "height": h // f} for f in (8, 4, 2, 1)]}
IIIF_INFO = info_extras
The InfoExtras dataclass is a typed alternative to the dict. At
IIIF_IMAGE_API_VERSION = 2 only sizes/tiles are accepted (v3-only keys
raise ImproperlyConfigured). Unset ⇒ output unchanged.
Important
These are declarations, not measurements. djiiif emits exactly what you configure and never probes the image server, so the values must match what that server really does (its tile size, its maximum request dimensions, …).
Rather than writing these views yourself, you can mount djiiif’s drop-in views.