dynamic location as a starting point
This commit is contained in:
parent
cca263c605
commit
1ecdc89a68
7 changed files with 63 additions and 13 deletions
|
@ -470,6 +470,22 @@ class CustomLocationProxyMixin:
|
|||
def get_custom_location(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
return self.get_custom_location() is not None
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self.get_custom_location().x
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self.get_custom_location().y
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return self.get_custom_location().level
|
||||
|
||||
def serialize_position(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -550,6 +566,9 @@ class Position(CustomLocationProxyMixin, models.Model):
|
|||
coordinates_id = models.CharField(_('coordinates'), null=True, max_length=48)
|
||||
api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret)
|
||||
|
||||
can_search = True
|
||||
can_describe = False
|
||||
|
||||
coordinates = LocationById()
|
||||
|
||||
class Meta:
|
||||
|
@ -583,8 +602,8 @@ class Position(CustomLocationProxyMixin, models.Model):
|
|||
custom_location = self.get_custom_location()
|
||||
if custom_location is None:
|
||||
return {
|
||||
'id': self.secret,
|
||||
'slug': self.secret,
|
||||
'id': 'p:%s' % self.secret,
|
||||
'slug': 'p:%s' % self.secret,
|
||||
'available': False,
|
||||
'icon': 'my_location',
|
||||
'title': self.name,
|
||||
|
@ -606,6 +625,18 @@ class Position(CustomLocationProxyMixin, models.Model):
|
|||
})
|
||||
return result
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
return 'p:%s' % self.secret
|
||||
|
||||
def serialize(self, *args, **kwargs):
|
||||
return self.serialize_position()
|
||||
|
||||
def get_geometry(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
level_id = None
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
super().save(*args, **kwargs)
|
||||
|
|
|
@ -4,7 +4,7 @@ import re
|
|||
from collections import OrderedDict
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
from typing import List, Mapping, Optional
|
||||
from typing import List, Mapping, Optional, Union
|
||||
|
||||
from django.apps import apps
|
||||
from django.db.models import Prefetch, Q
|
||||
|
@ -18,7 +18,7 @@ from c3nav.mapdata.models.access import AccessPermission
|
|||
from c3nav.mapdata.models.geometry.base import GeometryMixin
|
||||
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin, Space
|
||||
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
|
||||
from c3nav.mapdata.models.locations import LocationRedirect, LocationSlug, SpecificLocation
|
||||
from c3nav.mapdata.models.locations import LocationRedirect, LocationSlug, Position, SpecificLocation
|
||||
from c3nav.mapdata.utils.cache.local import LocalCacheProxy
|
||||
from c3nav.mapdata.utils.models import get_submodels
|
||||
|
||||
|
@ -206,12 +206,18 @@ def get_location_by_id_for_request(pk, request):
|
|||
if isinstance(pk, str):
|
||||
if pk.isdigit():
|
||||
pk = int(pk)
|
||||
elif pk.startswith('p:'):
|
||||
try:
|
||||
# return immediately, don't cache for obvious reasons
|
||||
return Position.objects.get(secret=pk[2:])
|
||||
except Position.DoesNotExist:
|
||||
return None
|
||||
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]:
|
||||
def get_location_by_slug_for_request(slug: str, request) -> Optional[Union[LocationSlug, Position]]:
|
||||
cache_key = 'mapdata:location:by_slug:%s:%s' % (AccessPermission.cache_key_for_request(request), slug)
|
||||
location = proxied_cache.get(cache_key, None)
|
||||
if location is not None:
|
||||
|
@ -221,6 +227,12 @@ def get_location_by_slug_for_request(slug: str, request) -> Optional[LocationSlu
|
|||
location = get_custom_location_for_request(slug, request)
|
||||
if location is None:
|
||||
return None
|
||||
elif slug.startswith('p:'):
|
||||
try:
|
||||
# return immediately, don't cache for obvious reasons
|
||||
return Position.objects.get(secret=slug[2:])
|
||||
except Position.DoesNotExist:
|
||||
return None
|
||||
elif ':' in slug:
|
||||
code, pk = slug.split(':', 1)
|
||||
model_name = LocationSlug.LOCATION_TYPE_BY_CODE.get(code)
|
||||
|
|
|
@ -7,6 +7,7 @@ from rest_framework.viewsets import ViewSet
|
|||
|
||||
from c3nav.mapdata.api import api_stats_clean_location_value
|
||||
from c3nav.mapdata.models.access import AccessPermission
|
||||
from c3nav.mapdata.models.locations import Position
|
||||
from c3nav.mapdata.utils.cache.stats import increment_cache_key
|
||||
from c3nav.mapdata.utils.locations import visible_locations_for_request
|
||||
from c3nav.routing.exceptions import LocationUnreachable, NoRouteFound, NotYetRoutable
|
||||
|
@ -71,8 +72,8 @@ class RoutingViewSet(ViewSet):
|
|||
|
||||
return Response({
|
||||
'request': {
|
||||
'origin': form.cleaned_data['origin'].pk,
|
||||
'destination': form.cleaned_data['destination'].pk,
|
||||
'origin': self.get_request_pk(form.cleaned_data['origin']),
|
||||
'destination': self.get_request_pk(form.cleaned_data['destination']),
|
||||
},
|
||||
'options': options.serialize(),
|
||||
'report_issue_url': reverse('site.report_create', kwargs={
|
||||
|
@ -83,6 +84,9 @@ class RoutingViewSet(ViewSet):
|
|||
'result': route.serialize(locations=visible_locations_for_request(request)),
|
||||
})
|
||||
|
||||
def get_request_pk(self, location):
|
||||
return location.slug if isinstance(location, Position) else location.pk
|
||||
|
||||
@action(detail=False, methods=['get', 'post'])
|
||||
def options(self, request, *args, **kwargs):
|
||||
options = RouteOptions.get_for_request(request)
|
||||
|
|
|
@ -12,7 +12,10 @@ def describe_location(location, locations):
|
|||
final_location = locations.get(location.pk)
|
||||
if final_location is not None:
|
||||
location = final_location
|
||||
return location.serialize(include_type=True, detailed=False, simple_geometry=True)
|
||||
result = location.serialize(include_type=True, detailed=False, simple_geometry=True)
|
||||
if hasattr(location, 'serialize_position'):
|
||||
result.update(location.serialize_position())
|
||||
return result
|
||||
|
||||
|
||||
class Route:
|
||||
|
@ -170,7 +173,6 @@ class Route:
|
|||
|
||||
options_summary = ', '.join(str(s) for s in options_summary)
|
||||
|
||||
|
||||
return OrderedDict((
|
||||
('origin', describe_location(self.origin, locations)),
|
||||
('destination', describe_location(self.destination, locations)),
|
||||
|
|
|
@ -328,8 +328,8 @@ class Router:
|
|||
if poi.space_id not in restrictions.spaces and poi.access_restriction_id not in restrictions),
|
||||
))
|
||||
elif isinstance(location, (CustomLocation, CustomLocationProxyMixin)):
|
||||
if isinstance(location, CustomLocationProxyMixin):
|
||||
location = location.get_custom_location()
|
||||
if isinstance(location, CustomLocationProxyMixin) and not location.available:
|
||||
raise LocationUnreachable
|
||||
point = Point(location.x, location.y)
|
||||
location = RouterPoint(location)
|
||||
space = self.space_for_point(location.level.pk, point, restrictions)
|
||||
|
|
|
@ -1547,6 +1547,7 @@ c3nav = {
|
|||
$.getJSON('/api/locations/' + location.id + '/geometry/', c3nav._location_geometry_loaded);
|
||||
}
|
||||
|
||||
if (!location.point) return;
|
||||
var point = c3nav._location_point_overrides[location.id] || location.point.slice(1),
|
||||
latlng = L.GeoJSON.coordsToLatLng(point),
|
||||
buttons = $('#location-popup-buttons').clone();
|
||||
|
|
|
@ -4,9 +4,9 @@ from c3nav.site.views import (about_view, access_redeem_view, account_view, chan
|
|||
login_view, logout_view, map_index, position_create, position_detail, position_list,
|
||||
position_set, qr_code, register_view, report_create, report_detail, report_list)
|
||||
|
||||
slug = r'(?P<slug>[a-z0-9-_.:]+)'
|
||||
slug = r'(?P<slug>[a-zA-Z0-9-_.:]+)'
|
||||
coordinates = r'(?P<coordinates>[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)'
|
||||
slug2 = r'(?P<slug2>[a-z0-9-_.:]+)'
|
||||
slug2 = r'(?P<slug2>[a-zA-Z0-9-_.:]+)'
|
||||
details = r'(?P<details>details/)?'
|
||||
nearby = r'(?P<nearby>nearby/)?'
|
||||
options = r'(?P<options>options/)?'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue