Skip to content
Snippets Groups Projects
Commit e67ded96 authored by Bastien Abadie's avatar Bastien Abadie
Browse files

Split documents serializers in several files

See merge request !77
parents ea8057ea 81dd584e
No related branches found
No related tags found
1 merge request!77Split serializers
......@@ -7,14 +7,16 @@ from rest_framework import status
from django.conf import settings
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from arkindex.documents.serializers import \
ElementSerializer, CorpusSerializer, PageLightSerializer, \
TranscriptionSearchResultSerializer, ActSearchResultSerializer, \
from arkindex.documents.serializers.elements import \
ElementSerializer, CorpusSerializer, PageLightSerializer, ActSerializer, SurfaceSerializer
from arkindex.documents.serializers.transcriptions import \
TranscriptionsSerializer, TranscriptionCreateSerializer
from arkindex.documents.serializers.search import \
TranscriptionSearchResultSerializer, ActSearchResultSerializer
from arkindex.documents.serializers.iiif import \
VolumeManifestSerializer, ActManifestSerializer, \
PageAnnotationListSerializer, PageActAnnotationListSerializer, \
SurfaceAnnotationListSerializer, TranscriptionSearchAnnotationListSerializer, \
ActSerializer, SurfaceSerializer, \
TranscriptionCreateSerializer, TranscriptionsSerializer
SurfaceAnnotationListSerializer, TranscriptionSearchAnnotationListSerializer
from arkindex.documents.models import \
Element, ElementType, Page, Act, Transcription, Corpus, TranscriptionType
from arkindex.documents.search import \
......
from rest_framework import serializers
from arkindex.documents.models import \
Element, ElementType, Page, PageType, PageDirection, Act, Corpus, MetaData, MetaType
from arkindex.images.serializers import ZoneSerializer, ImageSerializer
from arkindex.dataimport.serializers import RevisionSerializer
from arkindex.project.serializer_fields import EnumField, ViewerURLField
class MetaDataSerializer(serializers.ModelSerializer):
"""
Serialises some Metadata for any Element
"""
type = EnumField(MetaType)
revision = RevisionSerializer()
class Meta:
model = MetaData
fields = (
'id',
'type',
'name',
'value',
'revision',
)
class ElementLightSerializer(serializers.ModelSerializer):
"""
Serialises a Element
"""
type = EnumField(ElementType)
class Meta:
model = Element
fields = (
'id',
'type',
'name',
)
class PageLightSerializer(serializers.ModelSerializer):
"""
Serialises a Page
"""
page_type = EnumField(PageType)
direction = EnumField(PageDirection)
image = ImageSerializer(source='zone.image')
class Meta:
model = Page
fields = (
'id',
'page_type',
'nb',
'direction',
'display_name',
'image',
)
class ElementSerializer(serializers.ModelSerializer):
"""
Fully Serialises a document
"""
type = EnumField(ElementType)
# TODO: detect correct manifest per element type
viewer_url = ViewerURLField('api:volume-manifest')
class Meta:
model = Element
fields = (
'id',
'type',
'name',
'viewer_url',
)
class ActSerializer(serializers.ModelSerializer):
"""
Serialize an act with its parents and children
and metadatas
"""
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
source='parent_elements',
read_only=True,
)
children = ElementLightSerializer(source='child_elements', read_only=True, many=True)
metadatas = MetaDataSerializer(read_only=True, many=True)
class Meta:
model = Act
fields = (
'id',
'name',
'number',
'parents',
'children',
'metadatas',
)
read_only_fields = ('id', )
class SurfaceSerializer(serializers.ModelSerializer):
"""
Serialize a surface with its page, image and zone
"""
zone = ZoneSerializer()
page = PageLightSerializer()
class Meta:
model = Element
fields = (
'id',
'name',
'page',
'zone',
)
class CorpusSerializer(serializers.ModelSerializer):
"""
Serialize a corpus
"""
class Meta:
model = Corpus
fields = ('id', 'name')
# flake8: noqa
from arkindex.documents.serializers.iiif.manifests import VolumeManifestSerializer, ActManifestSerializer
from arkindex.documents.serializers.iiif.annotations import \
PageAnnotationListSerializer, PageActAnnotationListSerializer, \
SurfaceAnnotationListSerializer, TranscriptionSearchAnnotationListSerializer
from abc import ABC, abstractmethod
from django.conf import settings
from rest_framework import serializers
from arkindex.documents.models import Element, ElementType, Act, Page, Transcription
from arkindex.project.tools import build_absolute_url
class AnnotationSerializer(ABC, serializers.BaseSerializer):
"""
Serialize an element into a IIIF annotation
"""
@abstractmethod
def get_url(self, element):
"""Get an element's ID URL"""
def get_resource(self, element):
"""Get the annotation resource for a given element."""
return {
"@id": self.get_url(),
"@type": "cnt:ContentAsText",
"chars": element.name,
"format": "text/plain"
}
def get_target(self, element):
"""Get the target canvas (`on` property) for a given element."""
assert hasattr(element, 'zone')
return "{0}#xywh={1.x},{1.y},{1.width},{1.height}".format(
element.zone.image.get_thumbnail_url(max_width=None, max_height=None),
element.zone.polygon)
def to_representation(self, element):
assert isinstance(element, (Element, Transcription))
assert 'request' in self.context, "A request is required to generate absolute URLs"
return {
"@id": self.get_url(element),
"@type": "oa:Annotation",
"motivation": "sc:painting",
"on": self.get_target(element),
"resource": self.get_resource(element),
}
class TranscriptionAnnotationSerializer(AnnotationSerializer):
"""
Serialize a transcription into a IIIF annotation
"""
def get_url(self, ts):
return build_absolute_url(
ts,
self.context['request'],
'api:transcription-manifest',
id_argument='page_pk',
transcription_pk=ts.id,
)
def get_resource(self, ts):
return {
"@id": self.get_url(ts),
"@type": "cnt:ContentAsText",
"chars": ts.text,
"format": "text/plain"
}
class TranscriptionSearchAnnotationSerializer(TranscriptionAnnotationSerializer):
def get_target(self, element):
assert isinstance(element, Transcription)
url = build_absolute_url(element.element, self.context['request'], 'api:canvas-manifest')
return "{0}#xywh={1.x},{1.y},{1.width},{1.height}".format(url, element.zone.polygon)
class SurfaceAnnotationSerializer(AnnotationSerializer):
"""
Serialize a surface into a IIIF annotation
"""
def get_url(self, surface):
return build_absolute_url(
surface,
self.context['request'],
'api:surface-manifest',
id_argument='page_pk',
surface_pk=surface.id,
)
def get_resource(self, surface):
act = Act.objects.get_ascending(surface.id)[0]
chars = 'Act {}'.format(act.number) if act is not None else 'Unknown act'
return {
"@id": self.get_url(surface),
"@type": "cnt:ContentAsText",
"chars": chars,
"format": "text/plain"
}
class AnnotationListSerializer(ABC, serializers.BaseSerializer):
"""
Serialize a list of serialized annotations into a IIIF annotation list
"""
annotation_serializer = AnnotationSerializer
def to_representation(self, obj):
assert 'request' in self.context, "A request is required to generate absolute URLs"
return {
"@context": settings.IIIF_PRESENTATION_CONTEXT,
"@id": self.context['request'].build_absolute_uri(),
"@type": "sc:AnnotationList",
"resources": self.annotation_serializer(
self.get_elements(obj),
context=self.context,
many=True
).data
}
@abstractmethod
def get_elements(self, obj):
"Get a list of elements to serialize as annotations."
class PageAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a page's transcriptions into a IIIF annotation list
"""
annotation_serializer = TranscriptionAnnotationSerializer
def get_elements(self, page):
assert isinstance(page, Page)
return page.transcriptions.all()
class PageActAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize an page's acts into a IIIF annotation list
"""
annotation_serializer = SurfaceAnnotationSerializer
def get_elements(self, page):
assert isinstance(page, Page)
if page.zone is None:
return []
return Element.objects.filter(type=ElementType.Surface, zone__image=page.zone.image)
class SurfaceAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a single surface into a IIIF annotation list
"""
annotation_serializer = SurfaceAnnotationSerializer
def get_elements(self, surface):
assert isinstance(surface, Element) and surface.type == ElementType.Surface
return [surface]
def to_representation(self, surface):
serialized = super().to_representation(surface)
query = self.context['request'].query_params.get('q')
# When there's a search query, add all transcriptions that contain the query
# as serialized annotations in the list's resources
if query:
serialized['resources'].extend(
TranscriptionAnnotationSerializer(
Transcription.objects.filter(
zone__image=surface.zone.image,
zone__polygon__in=surface.zone.polygon,
text__icontains=query,
score__gte=0.5,
),
context=self.context,
many=True
).data
)
return serialized
class SearchAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a list of serialized annotations into a search result annotation list
"""
def to_representation(self, obj):
serialized = super().to_representation(obj)
serialized['@context'] = settings.IIIF_SEARCH_CONTEXT
serialized['within'] = {
"@type": "sc:Layer",
"total": len(serialized['resources']),
}
serialized['startIndex'] = 0
serialized['hits'] = [
{
"@type": "search:Hit",
"annotations": [anno['@id']],
"match": self.get_match(anno),
}
for anno in serialized['resources']
]
return serialized
def get_match(self, anno):
"""Get a match text for an annotation.
This is optional in the Search API but mandatory with Mirador"""
return anno['resource']['chars']
class TranscriptionSearchAnnotationListSerializer(SearchAnnotationListSerializer):
"""
Serialize a transcription search result into an annotation list
"""
annotation_serializer = TranscriptionSearchAnnotationSerializer
def get_elements(self, obj):
return obj
from abc import ABC, abstractmethod
from django.conf import settings
from rest_framework import serializers
from arkindex.documents.models import Element, ElementType, Transcription, Page, \
PageType, PageDirection, Act, Corpus, MetaData, MetaType, TranscriptionType
from arkindex.documents.models import Element, ElementType, Page, Act
from arkindex.images.models import Image, Zone
from arkindex.images.serializers import ZoneSerializer, ImageSerializer
from arkindex.dataimport.serializers import RevisionSerializer
from arkindex.project.serializer_fields import EnumField, ViewerURLField
from arkindex.project.tools import sslify_url
from django.urls import reverse
from arkindex.project.tools import sslify_url, build_absolute_url
import urllib.parse
def build_absolute_url(element, request, name, id_argument='pk', **kwargs):
"""Build an absolute URL for a specified view using the element ID."""
kwargs[id_argument] = str(element.id)
return request.build_absolute_uri(reverse(name, kwargs=kwargs))
class MetaDataSerializer(serializers.ModelSerializer):
"""
Serialises some Metadata for any Element
"""
type = EnumField(MetaType)
revision = RevisionSerializer()
class Meta:
model = MetaData
fields = (
'id',
'type',
'name',
'value',
'revision',
)
class TranscriptionSerializer(serializers.ModelSerializer):
"""
Serialises a Transcription
issued from a search
"""
type = EnumField(ElementType)
class Meta:
model = Transcription
fields = (
'id',
'type',
'text',
'score',
)
class ElementLightSerializer(serializers.ModelSerializer):
"""
Serialises a Element
"""
type = EnumField(ElementType)
class Meta:
model = Element
fields = (
'id',
'type',
'name',
)
class PageLightSerializer(serializers.ModelSerializer):
"""
Serialises a Page
"""
page_type = EnumField(PageType)
direction = EnumField(PageDirection)
image = ImageSerializer(source='zone.image')
class Meta:
model = Page
fields = (
'id',
'page_type',
'nb',
'direction',
'display_name',
'image',
)
class ElementSerializer(serializers.ModelSerializer):
"""
Fully Serialises a document
"""
type = EnumField(ElementType)
# TODO: detect correct manifest per element type
viewer_url = ViewerURLField('api:volume-manifest')
class Meta:
model = Element
fields = (
'id',
'type',
'name',
'viewer_url',
)
class ActSerializer(serializers.ModelSerializer):
"""
Serialize an act with its parents and children
and metadatas
"""
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
source='parent_elements',
read_only=True,
)
children = ElementLightSerializer(source='child_elements', read_only=True, many=True)
metadatas = MetaDataSerializer(read_only=True, many=True)
class Meta:
model = Act
fields = (
'id',
'name',
'number',
'parents',
'children',
'metadatas',
)
read_only_fields = ('id', )
class SurfaceSerializer(serializers.ModelSerializer):
"""
Serialize a surface with its page, image and zone
"""
zone = ZoneSerializer()
page = PageLightSerializer()
class Meta:
model = Element
fields = (
'id',
'name',
'page',
'zone',
)
class CorpusSerializer(serializers.ModelSerializer):
"""
Serialize a corpus
"""
class Meta:
model = Corpus
fields = ('id', 'name')
class TranscriptionCreateSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
"""
element = serializers.PrimaryKeyRelatedField(queryset=Element.objects.all())
polygon = serializers.ListField(
child=serializers.ListField(
child=serializers.IntegerField(),
min_length=2,
max_length=2
),
min_length=3
)
text = serializers.CharField()
score = serializers.FloatField(min_value=0, max_value=1)
type = EnumField(TranscriptionType)
class TranscriptionBulkSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
in Bulk (used by serializer below)
Note: no element !
"""
polygon = serializers.ListField(
child=serializers.ListField(
child=serializers.IntegerField(),
min_length=2,
max_length=2
),
min_length=3
)
text = serializers.CharField()
score = serializers.FloatField(min_value=0, max_value=1)
type = EnumField(TranscriptionType)
class TranscriptionsSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
in Bulk (uses serializer above) on a common parent
"""
transcriptions = TranscriptionBulkSerializer(many=True)
parent = serializers.PrimaryKeyRelatedField(queryset=Element.objects.all())
image = serializers.PrimaryKeyRelatedField(queryset=Image.objects.all())
class TranscriptionSearchResultSerializer(serializers.ModelSerializer):
"""
Link between objects & their search indexation
"""
type = EnumField(ElementType)
zone = ZoneSerializer()
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
source='parent_paths',
)
class Meta:
model = Transcription
fields = (
'id',
'type',
'text',
'score',
'zone',
'parents',
)
class ActSearchResultSerializer(serializers.ModelSerializer):
"""
Serialize an act
"""
transcriptions = TranscriptionSerializer(many=True, source='transcriptions_results')
surfaces = ZoneSerializer(many=True)
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
read_only=True,
)
viewer_url = ViewerURLField('api:act-manifest')
class Meta:
model = Act
fields = (
'id',
'name',
'number',
'transcriptions',
'surfaces',
'parents',
'viewer_url',
)
class ImageResourceManifestSerializer(serializers.BaseSerializer):
"""
Serialize an image into a IIIF resource.
......@@ -485,220 +228,3 @@ class ActManifestSerializer(ManifestSerializer):
for p in ordered_pages:
p.act = act
return ordered_pages
class AnnotationSerializer(ABC, serializers.BaseSerializer):
"""
Serialize an element into a IIIF annotation
"""
@abstractmethod
def get_url(self, element):
"""Get an element's ID URL"""
def get_resource(self, element):
"""Get the annotation resource for a given element."""
return {
"@id": self.get_url(),
"@type": "cnt:ContentAsText",
"chars": element.name,
"format": "text/plain"
}
def get_target(self, element):
"""Get the target canvas (`on` property) for a given element."""
assert hasattr(element, 'zone')
return "{0}#xywh={1.x},{1.y},{1.width},{1.height}".format(
element.zone.image.get_thumbnail_url(max_width=None, max_height=None),
element.zone.polygon)
def to_representation(self, element):
assert isinstance(element, (Element, Transcription))
assert 'request' in self.context, "A request is required to generate absolute URLs"
return {
"@id": self.get_url(element),
"@type": "oa:Annotation",
"motivation": "sc:painting",
"on": self.get_target(element),
"resource": self.get_resource(element),
}
class TranscriptionAnnotationSerializer(AnnotationSerializer):
"""
Serialize a transcription into a IIIF annotation
"""
def get_url(self, ts):
return build_absolute_url(
ts,
self.context['request'],
'api:transcription-manifest',
id_argument='page_pk',
transcription_pk=ts.id,
)
def get_resource(self, ts):
return {
"@id": self.get_url(ts),
"@type": "cnt:ContentAsText",
"chars": ts.text,
"format": "text/plain"
}
class TranscriptionSearchAnnotationSerializer(TranscriptionAnnotationSerializer):
def get_target(self, element):
assert isinstance(element, Transcription)
url = build_absolute_url(element.element, self.context['request'], 'api:canvas-manifest')
return "{0}#xywh={1.x},{1.y},{1.width},{1.height}".format(url, element.zone.polygon)
class SurfaceAnnotationSerializer(AnnotationSerializer):
"""
Serialize a surface into a IIIF annotation
"""
def get_url(self, surface):
return build_absolute_url(
surface,
self.context['request'],
'api:surface-manifest',
id_argument='page_pk',
surface_pk=surface.id,
)
def get_resource(self, surface):
act = Act.objects.get_ascending(surface.id)[0]
chars = 'Act {}'.format(act.number) if act is not None else 'Unknown act'
return {
"@id": self.get_url(surface),
"@type": "cnt:ContentAsText",
"chars": chars,
"format": "text/plain"
}
class AnnotationListSerializer(ABC, serializers.BaseSerializer):
"""
Serialize a list of serialized annotations into a IIIF annotation list
"""
annotation_serializer = AnnotationSerializer
def to_representation(self, obj):
assert 'request' in self.context, "A request is required to generate absolute URLs"
return {
"@context": settings.IIIF_PRESENTATION_CONTEXT,
"@id": self.context['request'].build_absolute_uri(),
"@type": "sc:AnnotationList",
"resources": self.annotation_serializer(
self.get_elements(obj),
context=self.context,
many=True
).data
}
@abstractmethod
def get_elements(self, obj):
"Get a list of elements to serialize as annotations."
class PageAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a page's transcriptions into a IIIF annotation list
"""
annotation_serializer = TranscriptionAnnotationSerializer
def get_elements(self, page):
assert isinstance(page, Page)
return page.transcriptions.all()
class PageActAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize an page's acts into a IIIF annotation list
"""
annotation_serializer = SurfaceAnnotationSerializer
def get_elements(self, page):
assert isinstance(page, Page)
if page.zone is None:
return []
return Element.objects.filter(type=ElementType.Surface, zone__image=page.zone.image)
class SurfaceAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a single surface into a IIIF annotation list
"""
annotation_serializer = SurfaceAnnotationSerializer
def get_elements(self, surface):
assert isinstance(surface, Element) and surface.type == ElementType.Surface
return [surface]
def to_representation(self, surface):
serialized = super().to_representation(surface)
query = self.context['request'].query_params.get('q')
# When there's a search query, add all transcriptions that contain the query
# as serialized annotations in the list's resources
if query:
serialized['resources'].extend(
TranscriptionAnnotationSerializer(
Transcription.objects.filter(
zone__image=surface.zone.image,
zone__polygon__in=surface.zone.polygon,
text__icontains=query,
score__gte=0.5,
),
context=self.context,
many=True
).data
)
return serialized
class SearchAnnotationListSerializer(AnnotationListSerializer):
"""
Serialize a list of serialized annotations into a search result annotation list
"""
def to_representation(self, obj):
serialized = super().to_representation(obj)
serialized['@context'] = settings.IIIF_SEARCH_CONTEXT
serialized['within'] = {
"@type": "sc:Layer",
"total": len(serialized['resources']),
}
serialized['startIndex'] = 0
serialized['hits'] = [
{
"@type": "search:Hit",
"annotations": [anno['@id']],
"match": self.get_match(anno),
}
for anno in serialized['resources']
]
return serialized
def get_match(self, anno):
"""Get a match text for an annotation.
This is optional in the Search API but mandatory with Mirador"""
return anno['resource']['chars']
class TranscriptionSearchAnnotationListSerializer(SearchAnnotationListSerializer):
"""
Serialize a transcription search result into an annotation list
"""
annotation_serializer = TranscriptionSearchAnnotationSerializer
def get_elements(self, obj):
return obj
from rest_framework import serializers
from arkindex.documents.models import Transcription, TranscriptionType, Act
from arkindex.documents.serializers.elements import ElementLightSerializer
from arkindex.documents.serializers.transcriptions import TranscriptionSerializer
from arkindex.images.serializers import ZoneSerializer
from arkindex.project.serializer_fields import EnumField, ViewerURLField
class TranscriptionSearchResultSerializer(serializers.ModelSerializer):
"""
Link between objects & their search indexation
"""
type = EnumField(TranscriptionType)
zone = ZoneSerializer()
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
source='parent_paths',
)
class Meta:
model = Transcription
fields = (
'id',
'type',
'text',
'score',
'zone',
'parents',
)
class ActSearchResultSerializer(serializers.ModelSerializer):
"""
Serialize an act
"""
transcriptions = TranscriptionSerializer(many=True, source='transcriptions_results')
surfaces = ZoneSerializer(many=True)
parents = serializers.ListField(
child=serializers.ListField(
child=ElementLightSerializer()
),
read_only=True,
)
viewer_url = ViewerURLField('api:act-manifest')
class Meta:
model = Act
fields = (
'id',
'name',
'number',
'transcriptions',
'surfaces',
'parents',
'viewer_url',
)
from rest_framework import serializers
from arkindex.documents.models import Element, Transcription, TranscriptionType
from arkindex.images.models import Image
from arkindex.project.serializer_fields import EnumField
class TranscriptionSerializer(serializers.ModelSerializer):
"""
Serialises a Transcription
issued from a search
"""
type = EnumField(TranscriptionType)
class Meta:
model = Transcription
fields = (
'id',
'type',
'text',
'score',
)
class TranscriptionCreateSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
"""
element = serializers.PrimaryKeyRelatedField(queryset=Element.objects.all())
polygon = serializers.ListField(
child=serializers.ListField(
child=serializers.IntegerField(),
min_length=2,
max_length=2
),
min_length=3
)
text = serializers.CharField()
score = serializers.FloatField(min_value=0, max_value=1)
type = EnumField(TranscriptionType)
class TranscriptionBulkSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
in Bulk (used by serializer below)
Note: no element !
"""
polygon = serializers.ListField(
child=serializers.ListField(
child=serializers.IntegerField(),
min_length=2,
max_length=2
),
min_length=3
)
text = serializers.CharField()
score = serializers.FloatField(min_value=0, max_value=1)
type = EnumField(TranscriptionType)
class TranscriptionsSerializer(serializers.Serializer):
"""
Allows for insertion of new transcriptions and zones
in Bulk (uses serializer above) on a common parent
"""
transcriptions = TranscriptionBulkSerializer(many=True)
parent = serializers.PrimaryKeyRelatedField(queryset=Element.objects.all())
image = serializers.PrimaryKeyRelatedField(queryset=Image.objects.all())
......@@ -44,16 +44,16 @@ api = [
# Placeholder URLs for IIIF IDs
url(r'^manifest/(?P<pk>[\w\-]+)/sequence/?$',
RedirectView.as_view(pattern_name='volume-manifest', permanent=False),
RedirectView.as_view(pattern_name='api:volume-manifest', permanent=False),
name='sequence-manifest'),
url(r'^manifest/(?P<pk>[\w\-]+)/canvas/?$',
RedirectView.as_view(pattern_name='page-act-manifest', permanent=False),
RedirectView.as_view(pattern_name='api:page-act-manifest', permanent=False),
name='canvas-manifest'),
url(r'^manifest/(?P<page_pk>[\w\-]+)/transcriptions/(?P<transcription_pk>[\w\-]+)/?$',
RedirectView.as_view(pattern_name='page-transcription-manifest', permanent=False),
RedirectView.as_view(pattern_name='api:page-transcription-manifest', permanent=False),
name='transcription-manifest'),
url(r'^manifest/(?P<page_pk>[\w\-]+)/surfaces/(?P<surface_pk>[\w\-]+)/?$',
RedirectView.as_view(pattern_name='page-act-manifest', permanent=False),
RedirectView.as_view(pattern_name='api:page-act-manifest', permanent=False),
name='surface-manifest'),
# Search transcriptions
......
from urllib.parse import urlsplit, SplitResult
from django.conf import settings
from django.urls import reverse
import Levenshtein
import random
import string
......@@ -68,3 +69,11 @@ def find_closest(name, queryset, min_ratio=0.8):
best_element, best_score = scores[0]
if best_score >= min_ratio:
return best_element
def build_absolute_url(element, request, name, id_argument='pk', **kwargs):
"""
Build an absolute URL for a specified view using the element ID.
"""
kwargs[id_argument] = str(element.id)
return request.build_absolute_uri(reverse(name, kwargs=kwargs))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment