diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py index 4b2b5fbe..48279b60 100644 --- a/src/c3nav/mapdata/models/locations.py +++ b/src/c3nav/mapdata/models/locations.py @@ -48,8 +48,9 @@ class LocationSlugManager(models.Manager): if self.model != LocationSlug: raise TypeError qs = self.get_queryset() - qs = qs.select_related('redirect__target', *('redirect__target__'+model._meta.default_related_name - for model in get_submodels(Location) + [LocationRedirect])) + qs = qs.select_related('locationredirects__target', + *('locationredirects__target__'+model._meta.default_related_name + for model in get_submodels(Location) + [LocationRedirect])) return qs @@ -108,15 +109,6 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model): class Meta: abstract = True - def serialize(self, detailed=True, **kwargs): - result = super().serialize(detailed=detailed, **kwargs) - if not detailed: - fields = ('id', 'type', 'slug', 'effective_slug', 'title', 'subtitle', 'icon', 'point', 'bounds', - 'grid_square', 'locations', 'on_top_of', 'effective_label_settings', 'label_override', - 'add_search', 'dynamic', 'locationtype', 'geometry') - result = {name: result[name] for name in fields if name in result} - return result - @property def add_search(self): return ' '.join(( @@ -495,6 +487,7 @@ class DynamicLocation(CustomLocationProxyMixin, SpecificLocation, models.Model): pass def serialize_position(self, request=None): + # todo: make this pretty custom_location = self.get_custom_location(request=request) if custom_location is None: return { @@ -505,7 +498,8 @@ class DynamicLocation(CustomLocationProxyMixin, SpecificLocation, models.Model): 'title': str(self.title), 'subtitle': '%s %s, %s' % (_('currently unavailable'), _('(moving)'), self.subtitle) } - result = custom_location.serialize(simple_geometry=True) + from c3nav.mapdata.schemas.models import CustomLocationSchema + result = CustomLocationSchema.model_validate(custom_location).model_dump() result.update({ 'available': True, 'id': self.pk, @@ -586,6 +580,7 @@ class Position(CustomLocationProxyMixin, models.Model): return result def serialize_position(self, request=None): + # todo: make this pretty custom_location = self.get_custom_location(request=request) if custom_location is None: return { @@ -596,7 +591,8 @@ class Position(CustomLocationProxyMixin, models.Model): 'title': self.name, 'subtitle': _('currently unavailable'), } - result = custom_location.serialize(simple_geometry=True) + from c3nav.mapdata.schemas.models import CustomLocationSchema + result = CustomLocationSchema.model_validate(custom_location).model_dump() result.update({ 'available': True, 'id': 'p:%s' % self.secret, @@ -619,20 +615,22 @@ class Position(CustomLocationProxyMixin, models.Model): def slug(self): return 'p:%s' % self.secret + @property + def subtitle(self): + return _('Position') + + @property + def icon(self): + return 'my_location' + + @property + def effective_icon(self): + return self.icon + @property def effective_slug(self): return self.slug - def serialize(self, *args, **kwargs): - return { - 'dynamic': True, - 'id': 'p:%s' % self.secret, - 'slug': 'p:%s' % self.secret, - 'icon': 'my_location', - 'title': self.name, - 'subtitle': _('Position'), - } - def details_display(self, **kwargs): return { 'id': self.pk, diff --git a/src/c3nav/mapdata/schemas/models.py b/src/c3nav/mapdata/schemas/models.py index 3b2982ac..126509b3 100644 --- a/src/c3nav/mapdata/schemas/models.py +++ b/src/c3nav/mapdata/schemas/models.py @@ -1,3 +1,4 @@ +from contextlib import suppress from typing import Annotated, ClassVar, Literal, Optional, Union, Any from django.db.models import Model @@ -545,6 +546,14 @@ class TrackablePositionSchema(BaseSchema): example="Near Bällebad" ) + @classmethod + def get_overrides(cls, value) -> dict: + from c3nav.mapdata.models.locations import Position + value: Position + return { + "id": value.slug, + } + class LocationTypeSchema(BaseSchema): locationtype: str = APIField(title="location type", @@ -695,6 +704,8 @@ class SlimDynamicLocationLocationSchema(SlimLocationMixin, FullDynamicLocationLo def get_locationtype(v: Any): if isinstance(v, Model): return v._meta.model_name + with suppress(AttributeError): + return v.locationtype return v["locationtype"] diff --git a/src/c3nav/mapdata/utils/locations.py b/src/c3nav/mapdata/utils/locations.py index 7b3a643c..08717560 100644 --- a/src/c3nav/mapdata/utils/locations.py +++ b/src/c3nav/mapdata/utils/locations.py @@ -40,7 +40,7 @@ def locations_for_request(request) -> Mapping[int, LocationSlug]: conditions = [] for model in get_submodels(Location): related_name = model._meta.default_related_name - for prefix in ('', 'redirect__target__'): + for prefix in ('', 'locationredirects__target__'): condition = Q(**{prefix + related_name + '__isnull': False}) # noinspection PyUnresolvedReferences condition &= model.q_for_request(request, prefix=prefix + related_name + '__') @@ -52,7 +52,7 @@ def locations_for_request(request) -> Mapping[int, LocationSlug]: ) locations = locations.filter(reduce(operator.or_, conditions)) - locations = locations.select_related('redirect', 'locationgroups__category') + locations = locations.select_related('locationredirects', 'locationgroups__category') # prefetch locationgroups base_qs = LocationGroup.qs_for_request(request).select_related('category', 'label_settings') @@ -275,6 +275,8 @@ def get_custom_location_for_request(slug: str, request): @dataclass class CustomLocation: + new_serialize: ClassVar = True + locationtype: ClassVar = "customlocation" can_search = True diff --git a/src/c3nav/routing/router.py b/src/c3nav/routing/router.py index 4e3aabfb..3bb171f7 100644 --- a/src/c3nav/routing/router.py +++ b/src/c3nav/routing/router.py @@ -534,6 +534,7 @@ CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'a 'areas', 'near_area', 'near_poi', 'nearby')) +# todo: make generic class BaseRouterProxy: def __init__(self, src): self.src = src