custom locations are something that we want
This commit is contained in:
parent
e0dc75c992
commit
dc46173668
3 changed files with 69 additions and 10 deletions
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue