diff --git a/apis_core/apis_entities/api_views.py b/apis_core/apis_entities/api_views.py new file mode 100644 index 0000000..4743c73 --- /dev/null +++ b/apis_core/apis_entities/api_views.py @@ -0,0 +1,74 @@ +from django.conf import settings +from django.http import Http404 +from django.shortcuts import redirect +from django.urls import reverse +from rest_framework.decorators import api_view +from rest_framework.generics import GenericAPIView +from rest_framework.response import Response +from rest_framework.settings import api_settings + +from apis_core.apis_metainfo.models import TempEntityClass, Uri +from .api_renderers import ( + EntityToTEI, +) + + +class GetEntityGeneric(GenericAPIView): + queryset = TempEntityClass.objects.all() + renderer_classes = tuple(api_settings.DEFAULT_RENDERER_CLASSES) + (EntityToTEI,) + if getattr(settings, "APIS_RENDERERS", None) is not None: + rend_add = tuple() + for rd in settings.APIS_RENDERERS: + rend_mod = __import__(rd) + for name, cls in rend_mod.__dict__.items(): + rend_add + (cls,) + renderer_classes += rend_add + + def get_object(self, pk, request): + try: + return TempEntityClass.objects_inheritance.get_subclass(pk=pk) + except TempEntityClass.DoesNotExist: + uri2 = Uri.objects.filter(uri=request.build_absolute_uri()) + if uri2.count() == 1: + return TempEntityClass.objects_inheritance.get_subclass( + pk=uri2[0].entity_id + ) + else: + raise Http404 + + def get(self, request, pk): + ent = self.get_object(pk, request) + data_view = request.GET.get("data-view", False) + format_param = request.GET.get("format", False) + requested_format = request.META.get("HTTP_ACCEPT") + if requested_format is not None: + if ( + requested_format.startswith("text/html") + and not data_view + and not format_param + ): + return redirect(ent) + res = EntitySerializer(ent, context={"request": request}) + return Response(res.data) + + +@api_view(["GET"]) +def uri_resolver(request): + uri = request.query_params.get("uri", None) + f = request.query_params.get("target_format", "gui") + if uri is None: + raise Http404 + else: + uri = Uri.objects.get(uri=uri) + if f == "gui": + ent = TempEntityClass.objects_inheritance.get_subclass(pk=uri.entity_id) + c_name = ent.__class__.__name__ + url = reverse( + "apis_core:apis_entities:generic_entities_detail_view", + kwargs={"pk": uri.entity_id, "entity": c_name.lower()}, + ) + else: + url = reverse( + "apis_core:apis_api2:GetEntityGeneric", kwargs={"pk": uri.entity_id} + ) + "?format={}".format(f) + return redirect(url) diff --git a/apis_core/apis_entities/autocomplete3.py b/apis_core/apis_entities/autocomplete3.py index 849765c..7a7b93f 100644 --- a/apis_core/apis_entities/autocomplete3.py +++ b/apis_core/apis_entities/autocomplete3.py @@ -129,7 +129,7 @@ def get(self, request, *args, **kwargs): test_stanbol = False more = True if not db_include: - for r in res[offset: offset + page_size]: + for r in res[offset : offset + page_size]: if int(r.pk) == int(ent_merge_pk): continue @@ -185,7 +185,7 @@ def get(self, request, *args, **kwargs): {"id": x.pk, "text": x.label} for x in vocab_model.objects.filter(name__icontains=q).order_by( "parent_class__name", "name" - )[offset: offset + page_size] + )[offset : offset + page_size] ] else: choices = [ @@ -193,7 +193,7 @@ def get(self, request, *args, **kwargs): for x in vocab_model.objects.filter( Q(name__icontains=q) | Q(name_reverse__icontains=q) ).order_by("parent_class__name", "name")[ - offset: offset + page_size + offset : offset + page_size ] ] elif direct == "reverse": @@ -201,7 +201,7 @@ def get(self, request, *args, **kwargs): {"id": x.pk, "text": x.label_reverse} for x in vocab_model.objects.filter( Q(name__icontains=q) | Q(name_reverse__icontains=q) - ).order_by("parent_class__name", "name")[offset: offset + page_size] + ).order_by("parent_class__name", "name")[offset : offset + page_size] ] if len(choices) == page_size: more = True diff --git a/apis_core/apis_entities/detail_views.py b/apis_core/apis_entities/detail_views.py index 36c6e99..aa66839 100644 --- a/apis_core/apis_entities/detail_views.py +++ b/apis_core/apis_entities/detail_views.py @@ -1,7 +1,7 @@ from django.conf import settings from django.db.models import Q -from django.http import Http404, HttpResponse -from django.shortcuts import get_object_or_404, redirect +from django.http import HttpResponse +from django.shortcuts import redirect from django.template.loader import select_template from django.views import View from django_tables2 import RequestConfig @@ -10,32 +10,7 @@ from apis_core.apis_metainfo.models import Uri from apis_core.apis_relations.models import AbstractRelation from apis_core.apis_relations.tables import LabelTableBase, get_generic_relations_table - -from .models import BASE_URI, TempEntityClass - - -def get_object_from_pk_or_uri(request, pk): - """checks if the given pk exists, if not checks if a matching apis-default uri exists - and returns its entity""" - try: - instance = TempEntityClass.objects_inheritance.get_subclass(pk=pk) - return instance - except TempEntityClass.DoesNotExist: - domain = BASE_URI - new_uri = f"{domain}entity/{pk}/" - uri2 = Uri.objects.filter(uri=new_uri) - if uri2.count() == 1: - instance = TempEntityClass.objects_inheritance.get_subclass( - pk=uri2[0].entity_id - ) - elif uri2.count() == 0: - temp_obj = get_object_or_404(Uri, uri=new_uri[:-1]) - instance = TempEntityClass.objects_inheritance.get_subclass( - pk=temp_obj.entity_id - ) - else: - raise Http404 - return instance +from apis_core.utils import get_object_from_pk_or_uri class GenericEntitiesDetailView(View): @@ -44,8 +19,7 @@ class GenericEntitiesDetailView(View): def get(self, request, *args, **kwargs): entity = kwargs["entity"].lower() pk = kwargs["pk"] - instance = get_object_from_pk_or_uri(request, pk) - # print(instance.id, pk) + instance = get_object_from_pk_or_uri(pk) if f"{instance.id}" == f"{pk}": pass else: diff --git a/apis_core/apis_entities/models.py b/apis_core/apis_entities/models.py index 8cb447f..1592bf3 100644 --- a/apis_core/apis_entities/models.py +++ b/apis_core/apis_entities/models.py @@ -8,6 +8,7 @@ from django.db.models import Q from django.db.models.signals import post_save from django.dispatch import receiver +from django.urls import reverse from apis_core.apis_metainfo.models import TempEntityClass, Uri from apis_core.apis_vocabularies.models import ( @@ -515,6 +516,12 @@ class Meta: "id", ] + def get_tei_url(self): + return reverse("apis_core:apis_tei:person_as_tei", kwargs={"pk": self.id}) + + def get_api_url(self): + return f"/apis/api/entities/person/{self.id}/" + class Place(AbstractEntity): kind = models.ForeignKey( @@ -534,6 +541,12 @@ class Meta: "id", ] + def get_tei_url(self): + return reverse("apis_core:apis_tei:place_as_tei", kwargs={"pk": self.id}) + + def get_api_url(self): + return f"/apis/api/entities/{self.__class__.__name__.lower()}/{self.id}/" + class Institution(AbstractEntity): kind = models.ForeignKey( @@ -545,6 +558,12 @@ class Meta: "id", ] + def get_tei_url(self): + return reverse("apis_core:apis_tei:org_as_tei", kwargs={"pk": self.id}) + + def get_api_url(self): + return f"/apis/api/entities/{self.__class__.__name__.lower()}/{self.id}/" + class Event(AbstractEntity): kind = models.ForeignKey( @@ -556,6 +575,9 @@ class Meta: "id", ] + def get_api_url(self): + return f"/apis/api/entities/{self.__class__.__name__.lower()}/{self.id}/" + class Work(AbstractEntity): kind = models.ForeignKey(WorkType, blank=True, null=True, on_delete=models.SET_NULL) @@ -565,6 +587,12 @@ class Meta: "id", ] + def get_tei_url(self): + return reverse("apis_core:apis_tei:work_as_tei", kwargs={"pk": self.id}) + + def get_api_url(self): + return f"/apis/api/entities/{self.__class__.__name__.lower()}/{self.id}/" + a_ents = getattr(settings, "APIS_ADDITIONAL_ENTITIES", False) diff --git a/apis_core/apis_entities/resolver_views.py b/apis_core/apis_entities/resolver_views.py new file mode 100644 index 0000000..a19bbae --- /dev/null +++ b/apis_core/apis_entities/resolver_views.py @@ -0,0 +1,35 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.http import Http404 +from django.shortcuts import redirect +from django.urls.exceptions import NoReverseMatch + +from apis_core.apis_metainfo.models import TempEntityClass, Uri + + +def uri_resolver(request): + uri = request.GET.get("uri", None) + # format_param = request.GET.get("format", False) + # requested_format = request.META.get("HTTP_ACCEPT") + if uri is None: + raise Http404 + else: + try: + uri = Uri.objects.get(uri=uri) + except ObjectDoesNotExist: + raise Http404 + entity = TempEntityClass.objects_inheritance.get_subclass(pk=uri.entity_id) + url = entity.get_absolute_url() + return redirect(url) + + +def entity_resolver(request, pk): + try: + TempEntityClass.objects.get(id=pk) + except ObjectDoesNotExist: + raise Http404 + entity = TempEntityClass.objects_inheritance.get_subclass(pk=pk) + try: + url = entity.get_absolute_url() + except NoReverseMatch: + raise Http404 + return redirect(url) diff --git a/apis_core/apis_entities/templates/apis_entities/detail_views/entity_detail_generic.html b/apis_core/apis_entities/templates/apis_entities/detail_views/entity_detail_generic.html index 8f95c60..b6f24f3 100644 --- a/apis_core/apis_entities/templates/apis_entities/detail_views/entity_detail_generic.html +++ b/apis_core/apis_entities/templates/apis_entities/detail_views/entity_detail_generic.html @@ -55,7 +55,7 @@

{% if object.get_next_url %}

- + @@ -69,7 +69,7 @@

General Info - + @@ -78,7 +78,7 @@

- {% if entity_type != 'event' %}| TEI{% endif %} + {% if entity_type != 'event' %}| TEI{% endif %}

{% block info-table %} diff --git a/apis_core/apis_entities/tests.py b/apis_core/apis_entities/tests.py index 8ff5788..b8757cf 100644 --- a/apis_core/apis_entities/tests.py +++ b/apis_core/apis_entities/tests.py @@ -5,7 +5,7 @@ from icecream import ic from apis_core.apis_entities.forms import get_entities_form -from apis_core.apis_entities.models import Person +from apis_core.apis_entities.models import Person, Place from apis_core.apis_metainfo.models import Uri from normdata.forms import NormDataImportForm from normdata.utils import ( @@ -30,9 +30,19 @@ class EntitiesTestCase(TestCase): ] def setUp(self): - # Create two users User.objects.create_user(**USER) + def test_001a_entity_resolver(self): + url = reverse("entity-resolver", kwargs={"pk": 4}) + r = client.get(url) + self.assertEqual(r.status_code, 404) + url = reverse("entity-resolver", kwargs={"pk": 44442344}) + r = client.get(url) + self.assertEqual(r.status_code, 404) + url = reverse("entity-resolver", kwargs={"pk": 1}) + r = client.get(url) + self.assertEqual(r.status_code, 302) + def test_001_list_view(self): for x in MODELS: try: @@ -275,3 +285,25 @@ def test_020_api_list_view(self): except Exception as e: print(value, e) continue + + def test_021_api_detail_view(self): + item = Person.objects.last() + r = client.get(item.get_api_url()) + self.assertTrue(r.status_code, 200) + item = Place.objects.last() + r = client.get(item.get_api_url()) + self.assertTrue(r.status_code, 200) + + def test_022_resolver_view(self): + target = Person.objects.last() + source = Person.objects.create(**{"name": "wirdgleichgemerged"}) + source_id = source.id + source_uri = f"https://pmb.acdh.oeaw.ac.at/entity/{source.id}/" + target.merge_with(source_id) + url = reverse("uri-resolver") + r = client.get(url) + self.assertTrue(r.status_code, 404) + r = client.get(f"{url}?uri={source_uri}") + self.assertTrue(r.status_code, 302) + r = client.get(f"{url}?uri=https://dasgibtsjagarnicht.com") + self.assertTrue(r.status_code, 404) diff --git a/apis_core/apis_tei/tei_urls.py b/apis_core/apis_tei/tei_urls.py index fecd00f..3b53df8 100644 --- a/apis_core/apis_tei/tei_urls.py +++ b/apis_core/apis_tei/tei_urls.py @@ -22,5 +22,5 @@ path("org/", views.org_as_tei, name="org_as_tei"), path("institution/", views.org_as_tei, name="org_as_tei"), path("work/", views.work_as_tei, name="work_as_tei"), - path("uri-to-tei", views.uri_to_tei, name="uri_to_tei"), + path("uri-to-tei/", views.uri_to_tei, name="uri_to_tei"), ] diff --git a/apis_core/apis_tei/views.py b/apis_core/apis_tei/views.py index be72f10..966a634 100644 --- a/apis_core/apis_tei/views.py +++ b/apis_core/apis_tei/views.py @@ -2,7 +2,7 @@ from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect -from apis_core.apis_entities.detail_views import get_object_from_pk_or_uri +from apis_core.utils import get_object_from_pk_or_uri from apis_core.apis_entities.models import Institution, Person, Place, Work from apis_core.apis_metainfo.models import Uri @@ -12,7 +12,7 @@ def person_as_tei(request, pk): full = request.GET.get("full") model = Person - res = get_object_from_pk_or_uri(request, pk) + res = get_object_from_pk_or_uri(pk) if not isinstance(res, model): return HttpResponse( f"Requested object is not an instance of {model.__name__}", @@ -26,7 +26,7 @@ def person_as_tei(request, pk): def place_as_tei(request, pk): full = request.GET.get("full") model = Place - res = get_object_from_pk_or_uri(request, pk) + res = get_object_from_pk_or_uri(pk) if not isinstance(res, model): return HttpResponse( f"Requested object is not an instance of {model.__name__}", @@ -40,7 +40,7 @@ def place_as_tei(request, pk): def work_as_tei(request, pk): full = request.GET.get("full") model = Work - res = get_object_from_pk_or_uri(request, pk) + res = get_object_from_pk_or_uri(pk) if not isinstance(res, model): return HttpResponse( f"Requested object is not an instance of {model.__name__}", @@ -54,7 +54,7 @@ def work_as_tei(request, pk): def org_as_tei(request, pk): full = request.GET.get("full") model = Institution - res = get_object_from_pk_or_uri(request, pk) + res = get_object_from_pk_or_uri(pk) if not isinstance(res, model): return HttpResponse( f"Requested object is not an instance of {model.__name__}", @@ -72,10 +72,10 @@ def uri_to_tei(request): uri_entity_id = uri.entity.id uri_entity_class = uri.entity.get_child_entity() uri_entity_class_name = uri_entity_class.__class__.__name__.lower() - redirect_url = f"/apis/entities/tei/{uri_entity_class_name}/{uri_entity_id}" + redirect_url = f"/apis/tei/{uri_entity_class_name}/{uri_entity_id}" return redirect(redirect_url) else: return HttpResponse( - f"no URI provided, please try e.g. uri-to-tei?uri=https://whatever.you/want", + "no URI provided, please try e.g. uri-to-tei?uri=https://whatever.you/want", content_type="text/plain", ) diff --git a/apis_core/utils.py b/apis_core/utils.py new file mode 100644 index 0000000..2f64f43 --- /dev/null +++ b/apis_core/utils.py @@ -0,0 +1,31 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.http import Http404 + +from django.shortcuts import get_object_or_404 + +# from apis_core.apis_entities.detail_views import get_object_from_pk_or_uri +from apis_core.apis_metainfo.models import TempEntityClass, Uri + + +def get_object_from_pk_or_uri(pk): + """checks if the given pk exists, if not checks if a matching apis-default uri exists + and returns its entity""" + try: + instance = TempEntityClass.objects_inheritance.get_subclass(pk=pk) + return instance + except ObjectDoesNotExist: + domain = "https://pmb.acdh.oeaw.ac.at/" + new_uri = f"{domain}entity/{pk}/" + uri2 = Uri.objects.filter(uri=new_uri) + if uri2.count() == 1: + instance = TempEntityClass.objects_inheritance.get_subclass( + pk=uri2[0].entity_id + ) + elif uri2.count() == 0: + temp_obj = get_object_or_404(Uri, uri=new_uri[:-1]) + instance = TempEntityClass.objects_inheritance.get_subclass( + pk=temp_obj.entity_id + ) + else: + raise Http404 + return instance diff --git a/archemd/views.py b/archemd/views.py index a31541d..f10fc5b 100644 --- a/archemd/views.py +++ b/archemd/views.py @@ -1,40 +1,13 @@ from django.core.exceptions import ObjectDoesNotExist -from django.http import Http404, HttpResponse, HttpResponseNotFound -from django.shortcuts import get_object_or_404 +from django.http import HttpResponse, HttpResponseNotFound -# from apis_core.apis_entities.detail_views import get_object_from_pk_or_uri -from apis_core.apis_metainfo.models import TempEntityClass, Uri +from apis_core.utils import get_object_from_pk_or_uri from .arche_md_utils import ArcheMd -# ToDo: remove this function when updating apis-core package -def get_object_from_pk_or_uri(request, pk): - """checks if the given pk exists, if not checks if a matching apis-default uri exists - and returns its entity""" - try: - instance = TempEntityClass.objects_inheritance.get_subclass(pk=pk) - return instance - except TempEntityClass.DoesNotExist: - domain = "https://pmb.acdh.oeaw.ac.at/" - new_uri = f"{domain}entity/{pk}/" - uri2 = Uri.objects.filter(uri=new_uri) - if uri2.count() == 1: - instance = TempEntityClass.objects_inheritance.get_subclass( - pk=uri2[0].entity_id - ) - elif uri2.count() == 0: - temp_obj = get_object_or_404(Uri, uri=new_uri[:-1]) - instance = TempEntityClass.objects_inheritance.get_subclass( - pk=temp_obj.entity_id - ) - else: - raise Http404 - return instance - - def entity_as_arche(request, pk): - res = get_object_from_pk_or_uri(request, pk) + res = get_object_from_pk_or_uri(pk) try: res = ArcheMd(res.id) except ObjectDoesNotExist: diff --git a/pmb/urls.py b/pmb/urls.py index cd15888..db699e7 100644 --- a/pmb/urls.py +++ b/pmb/urls.py @@ -3,10 +3,15 @@ from django.contrib import admin from django.urls import include, path +from apis_core.apis_entities import resolver_views + + urlpatterns = [ path("apis/", include("apis_core.urls", namespace="apis")), path("normdata/", include("normdata.urls", namespace="normdata")), path("admin/", admin.site.urls), path("arche/", include("archemd.urls", namespace="archemd")), + path("uri/", resolver_views.uri_resolver, name="uri-resolver"), + path("entity//", resolver_views.entity_resolver, name="entity-resolver"), path("", include("dumper.urls", namespace="dumper")), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)