From 40f19afc286e3a86f9b72c6abdd4af3bf24afe7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Wed, 4 Dec 2024 12:08:19 +0100 Subject: [PATCH] add locationredirect api endpoint with new_serialize --- src/c3nav/mapdata/api/mapdata.py | 8 ++++++-- src/c3nav/mapdata/models/locations.py | 19 ++++++++----------- src/c3nav/mapdata/schemas/models.py | 23 ++++++++++++++++++++++- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/c3nav/mapdata/api/mapdata.py b/src/c3nav/mapdata/api/mapdata.py index 403802fb..69c91ce7 100644 --- a/src/c3nav/mapdata/api/mapdata.py +++ b/src/c3nav/mapdata/api/mapdata.py @@ -15,7 +15,7 @@ from c3nav.mapdata.models import (Area, Building, Door, Hole, Level, LocationGro from c3nav.mapdata.models.access import AccessRestriction, AccessRestrictionGroup from c3nav.mapdata.models.geometry.space import (POI, Column, CrossDescription, LeaveDescription, LineObstacle, Obstacle, Ramp) -from c3nav.mapdata.models.locations import DynamicLocation, LabelSettings +from c3nav.mapdata.models.locations import DynamicLocation, LabelSettings, LocationRedirect from c3nav.mapdata.schemas.filters import (ByCategoryFilter, ByGroupFilter, ByOnTopOfFilter, FilterSchema, LevelGeometryFilter, SpaceGeometryFilter, BySpaceFilter, ByOverlayFilter) from c3nav.mapdata.schemas.model_base import schema_description, LabelSettingsSchema @@ -24,7 +24,7 @@ from c3nav.mapdata.schemas.models import (AccessRestrictionGroupSchema, AccessRe DynamicLocationSchema, HoleSchema, LeaveDescriptionSchema, LevelSchema, LineObstacleSchema, LocationGroupCategorySchema, LocationGroupSchema, ObstacleSchema, POISchema, RampSchema, SourceSchema, SpaceSchema, StairSchema, - DataOverlaySchema, DataOverlayFeatureSchema) + DataOverlaySchema, DataOverlayFeatureSchema, LocationRedirectSchema) mapdata_api_router = APIRouter(tags=["mapdata"]) @@ -191,6 +191,10 @@ mapdata_endpoints: dict[str, list[MapdataEndpoint]] = { model=LocationGroupCategory, schema=LocationGroupCategorySchema, ), + MapdataEndpoint( + model=LocationRedirect, + schema=LocationRedirectSchema, + ), MapdataEndpoint( model=Source, schema=SourceSchema, diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py index 59601383..4feaa2c6 100644 --- a/src/c3nav/mapdata/models/locations.py +++ b/src/c3nav/mapdata/models/locations.py @@ -445,22 +445,19 @@ class LocationGroup(Location, models.Model): class LocationRedirect(LocationSlug): + new_serialize = True + target = models.ForeignKey(LocationSlug, related_name='redirects', on_delete=models.CASCADE, verbose_name=_('target')) - def _serialize(self, include_type=True, **kwargs): - result = super()._serialize(include_type=include_type, **kwargs) - if type(self.target) == LocationSlug: - result['target'] = self.target.get_child().slug - else: - result['target'] = self.target.slug - if include_type: - result['type'] = 'redirect' - result.pop('id') - return result + @property + def target_slug(self): + if type(self.target) is LocationSlug: + return self.target.get_child().effective_slug + return self.target.effective_slug class Meta: - default_related_name = 'redirect' + default_related_name = 'locationredirects' class LabelSettings(SerializableMixin, models.Model): diff --git a/src/c3nav/mapdata/schemas/models.py b/src/c3nav/mapdata/schemas/models.py index 129b252a..3b2982ac 100644 --- a/src/c3nav/mapdata/schemas/models.py +++ b/src/c3nav/mapdata/schemas/models.py @@ -16,7 +16,7 @@ from c3nav.mapdata.schemas.model_base import (AnyLocationID, AnyPositionID, Cust WithAccessRestrictionSchema, WithLevelSchema, WithLineStringGeometrySchema, WithPointGeometrySchema, WithPolygonGeometrySchema, WithSpaceSchema, schema_definitions, - schema_description) + schema_description, LocationSlugSchema) from c3nav.mapdata.utils.geometry import smart_mapping from c3nav.mapdata.utils.json import format_geojson @@ -273,6 +273,27 @@ class LocationGroupSchema(LocationSchema, DjangoModelSchema): ) +class LocationRedirectSchema(LocationSlugSchema, DjangoModelSchema): + """ + A location group redirect describes a slug that, when used redirects to another location + """ + slug: NonEmptyStr = APIField( # todo: copy from somewhere? + title="location slug", + description="a slug is a unique way to refer to a location. while locations have a shared ID space, slugs" + "are meants to be human-readable and easy to remember.", + example="entrance", + ) + target: PositiveInt = APIField( + title="target", + description="location to redirect to", + ) + target_slug: NonEmptyStr = APIField( + title="effective target location slug", + description="effective slug of the target location", + example="lobby", + ) + + class LocationGroupCategorySchema(TitledSchema, DjangoModelSchema): """ A location group category can hold either one or multiple location groups.