custom locations are something that we want

This commit is contained in:
Laura Klünder 2017-11-28 20:15:31 +01:00
parent e0dc75c992
commit dc46173668
3 changed files with 69 additions and 10 deletions

View file

@ -24,8 +24,9 @@ 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, locations_for_request,
searchable_locations_for_request, visible_locations_for_request)
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, 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,6 +253,7 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet):
/{id}/ add ?show_redirect=1 to suppress redirects and show them as JSON.
"""
queryset = LocationSlug.objects.all()
lookup_value_regex = r'[^/]+'
@api_etag()
def list(self, request, *args, **kwargs):
@ -282,10 +284,7 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet):
detailed = 'detailed' in request.GET
geometry = 'geometry' in request.GET
if not pk.isdigit():
raise NotFound
location = locations_for_request(request).get(int(pk))
location = get_location_by_id_for_request(pk, request)
if location is None:
raise NotFound
@ -321,6 +320,7 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet):
class LocationBySlugViewSet(RetrieveModelMixin, GenericViewSet):
queryset = LocationSlug.objects.all()
lookup_field = 'slug'
lookup_value_regex = r'[^/]+'
@api_etag()
def retrieve(self, request, slug=None, *args, **kwargs):

View file

@ -1,4 +1,7 @@
import math
import operator
import re
from collections import OrderedDict
from functools import reduce
from itertools import chain
from typing import List, Mapping, Optional
@ -6,6 +9,7 @@ from typing import List, Mapping, Optional
from django.apps import apps
from django.core.cache import cache
from django.db.models import Prefetch, Q
from django.utils.translation import ugettext_lazy as _
from shapely.ops import cascaded_union
from c3nav.mapdata.models import Level, Location, LocationGroup, MapUpdate
@ -154,13 +158,26 @@ def locations_by_slug_for_request(request) -> Mapping[str, LocationSlug]:
return locations
def get_location_by_id_for_request(pk, request):
if isinstance(pk, str):
if pk.isdigit():
pk = int(pk)
else:
return get_custom_location_for_request(pk, request)
return locations_for_request(request).get(pk)
def get_location_by_slug_for_request(slug: str, request) -> Optional[LocationSlug]:
cache_key = 'mapdata:location:by_slug:%s:%s' % (AccessPermission.cache_key_for_request(request), slug)
location = cache.get(cache_key, None)
if location is not None:
return location
if ':' in slug:
if slug.startswith('c:'):
location = get_custom_location_for_request(slug, request)
if location is None:
return None
elif ':' in slug:
code, pk = slug.split(':', 1)
model_name = LocationSlug.LOCATION_TYPE_BY_CODE.get(code)
if model_name is None or not pk.isdigit():
@ -180,3 +197,45 @@ def get_location_by_slug_for_request(slug: str, request) -> Optional[LocationSlu
cache.set(cache_key, location, 300)
return location
def get_custom_location_for_request(slug: str, request):
match = re.match(r'^c:(?P<level>[a-z0-9-_]+):(?P<x>-?\d+(\.\d\d?)?):(?P<y>-?\d+(\.\d\d?)?)$', slug)
if match is None:
return None
level = locations_by_slug_for_request(request).get(match.group('level'))
if not isinstance(level, Level):
return None
return CustomLocation(level, float(match.group('x')), float(match.group('y')))
class CustomLocation:
can_search = True
def __init__(self, level, x, y):
self.pk = 'c:%s:%s:%s' % (level.short_label, x, y)
self.level = level
self.x = x
self.y = y
self.title = str(_('Coordinates'))
self.subtitle = str(_('%(level)s, x=%(x)s, y=%(y)s') % {'level': self.level.title,
'x': self.x,
'y': self.y})
def serialize(self, simple_geometry=False, geometry=True, **kwargs):
result = OrderedDict((
('id', self.pk),
('slug', self.pk),
('title', self.title),
('subtitle', self.subtitle),
))
if simple_geometry:
result['point'] = (self.level.pk, self.x, self.y)
result['bounds'] = ((int(math.floor(self.x)), int(math.floor(self.y))),
(int(math.ceil(self.x)), int(math.ceil(self.y))))
if geometry:
result['geometry'] = {
'type': 'Point',
'coordinates': (self.x, self.y)
}
return result

View file

@ -6,9 +6,9 @@ details = r'(?P<details>details/)?'
pos = r'(@(?P<level>[a-z0-9-_:]+),(?P<x>-?\d+(\.\d+)?),(?P<y>-?\d+(\.\d+)?),(?P<zoom>-?\d+(\.\d+)?))?'
urlpatterns = [
url(r'^(?P<mode>[l])/(?P<slug>[a-z0-9-_:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
url(r'^(?P<mode>[od])/(?P<slug>[a-z0-9-_:]+)/%s$' % pos, map_index, name='site.index'),
url(r'^r/(?P<slug>[a-z0-9-_:]+)/(?P<slug2>[a-z0-9-_:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
url(r'^(?P<mode>[l])/(?P<slug>[a-z0-9-_.:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
url(r'^(?P<mode>[od])/(?P<slug>[a-z0-9-_.:]+)/%s$' % pos, map_index, name='site.index'),
url(r'^r/(?P<slug>[a-z0-9-_.:]+)/(?P<slug2>[a-z0-9-_.:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
url(r'^(?P<mode>r)/%s$' % pos, map_index, name='site.index'),
url(r'^%s$' % pos, map_index, name='site.index')
]