diff --git a/src/c3nav/api/urls.py b/src/c3nav/api/urls.py index 55b877f6..77e2a879 100644 --- a/src/c3nav/api/urls.py +++ b/src/c3nav/api/urls.py @@ -9,9 +9,9 @@ from rest_framework.routers import SimpleRouter from c3nav.editor.api import ChangeSetViewSet, EditorViewSet from c3nav.mapdata.api import (AccessRestrictionViewSet, AreaViewSet, BuildingViewSet, ColumnViewSet, DoorViewSet, - HoleViewSet, LevelViewSet, LineObstacleViewSet, LocationGroupCategoryViewSet, - LocationGroupViewSet, LocationViewSet, MapViewSet, ObstacleViewSet, POIViewSet, - RampViewSet, SourceViewSet, SpaceViewSet, StairViewSet) + HoleViewSet, LevelViewSet, LineObstacleViewSet, LocationBySlugViewSet, + LocationGroupCategoryViewSet, LocationGroupViewSet, LocationViewSet, MapViewSet, + ObstacleViewSet, POIViewSet, RampViewSet, SourceViewSet, SpaceViewSet, StairViewSet) router = SimpleRouter() router.register(r'map', MapViewSet, base_name='map') @@ -31,6 +31,7 @@ router.register(r'sources', SourceViewSet) router.register(r'accessrestrictions', AccessRestrictionViewSet) router.register(r'locations', LocationViewSet) +router.register(r'locations/by_slug', LocationBySlugViewSet, base_name='location-by-slug') router.register(r'locationgroupcategories', LocationGroupCategoryViewSet) router.register(r'locationgroups', LocationGroupViewSet) diff --git a/src/c3nav/mapdata/api.py b/src/c3nav/mapdata/api.py index 8f9bc55c..6c75b96b 100644 --- a/src/c3nav/mapdata/api.py +++ b/src/c3nav/mapdata/api.py @@ -24,8 +24,8 @@ from c3nav.mapdata.models.geometry.space import (POI, Area, Column, LineObstacle from c3nav.mapdata.models.level import Level from c3nav.mapdata.models.locations import (Location, LocationGroupCategory, LocationRedirect, LocationSlug, SpecificLocation) -from c3nav.mapdata.utils.locations import (get_location_by_slug_for_request, searchable_locations_for_request, - visible_locations_for_request) +from c3nav.mapdata.utils.locations import (get_location_by_slug_for_request, locations_for_request, + searchable_locations_for_request, visible_locations_for_request) from c3nav.mapdata.utils.models import get_submodels @@ -252,7 +252,6 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet): /{id}/ add ?show_redirect=1 to suppress redirects and show them as JSON. """ queryset = LocationSlug.objects.all() - lookup_field = 'slug' @api_etag() def list(self, request, *args, **kwargs): @@ -277,6 +276,52 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet): return Response(result) + @api_etag() + def retrieve(self, request, pk=None, *args, **kwargs): + show_redirects = 'show_redirects' in request.GET + detailed = 'detailed' in request.GET + geometry = 'geometry' in request.GET + + if not pk.isdigit(): + raise NotFound + + location = locations_for_request(request).get(int(pk)) + + if location is None: + raise NotFound + + if isinstance(location, LocationRedirect): + if not show_redirects: + return redirect('../' + str(location.target.slug)) # todo: why does redirect/reverse not work here? + + return Response(location.serialize(include_type=True, detailed=detailed, + geometry=geometry, simple_geometry=True)) + + @detail_route(methods=['get']) + @api_etag() + def display(self, request, pk=None): + if not pk.isdigit(): + raise NotFound + + location = locations_for_request(request).get(int(pk)) + if location is None: + raise NotFound + + if isinstance(location, LocationRedirect): + return redirect('../' + str(location.target.pk) + '/display/') + + return Response(location.details_display()) + + @list_route(methods=['get']) + @api_etag(permissions=False) + def types(self, request): + return MapdataViewSet.list_types(get_submodels(Location), geomtype=False) + + +class LocationBySlugViewSet(RetrieveModelMixin, GenericViewSet): + queryset = LocationSlug.objects.all() + lookup_field = 'slug' + @api_etag() def retrieve(self, request, slug=None, *args, **kwargs): show_redirects = 'show_redirects' in request.GET @@ -307,11 +352,6 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet): return Response(location.details_display()) - @list_route(methods=['get']) - @api_etag(permissions=False) - def types(self, request): - return MapdataViewSet.list_types(get_submodels(Location), geomtype=False) - class SourceViewSet(MapdataViewSet): queryset = Source.objects.all()