first locations endpoint might… be… something?
This commit is contained in:
parent
d84226dc5c
commit
8b47a89865
4 changed files with 132 additions and 3 deletions
|
@ -82,6 +82,7 @@ class LocationSlug(SerializableMixin, models.Model):
|
||||||
|
|
||||||
def _serialize(self, **kwargs):
|
def _serialize(self, **kwargs):
|
||||||
result = super()._serialize(**kwargs)
|
result = super()._serialize(**kwargs)
|
||||||
|
result["locationtype"] = self.__class__.__name__.lower()
|
||||||
result['slug'] = self.get_slug()
|
result['slug'] = self.get_slug()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
from django.core.cache import cache
|
||||||
|
from ninja import Query
|
||||||
from ninja import Router as APIRouter
|
from ninja import Router as APIRouter
|
||||||
|
from ninja import Schema
|
||||||
|
from pydantic import Field as APIField
|
||||||
|
|
||||||
from c3nav.api.newauth import auth_responses
|
from c3nav.api.newauth import auth_responses
|
||||||
from c3nav.mapdata.models import Source
|
from c3nav.mapdata.models import Source
|
||||||
|
from c3nav.mapdata.models.access import AccessPermission
|
||||||
|
from c3nav.mapdata.schemas.models import AnyLocationSchema
|
||||||
from c3nav.mapdata.schemas.responses import BoundsSchema
|
from c3nav.mapdata.schemas.responses import BoundsSchema
|
||||||
|
from c3nav.mapdata.utils.locations import searchable_locations_for_request, visible_locations_for_request
|
||||||
|
|
||||||
map_api_router = APIRouter(tags=["map"])
|
map_api_router = APIRouter(tags=["map"])
|
||||||
|
|
||||||
|
@ -13,3 +20,43 @@ def bounds(request):
|
||||||
return {
|
return {
|
||||||
"bounds": Source.max_bounds(),
|
"bounds": Source.max_bounds(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LocationEndpointParameters(Schema):
|
||||||
|
searchable: bool = APIField(
|
||||||
|
False,
|
||||||
|
title='only list searchable locations',
|
||||||
|
description='if set, only searchable locations will be listed'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def can_access_geometry(request):
|
||||||
|
return True # todo: implementFd
|
||||||
|
|
||||||
|
|
||||||
|
@map_api_router.get('/locations/', response={200: list[AnyLocationSchema], **auth_responses},
|
||||||
|
summary="Get map boundaries")
|
||||||
|
def location_list(request, params: Query[LocationEndpointParameters]):
|
||||||
|
# todo: cache, visibility, etc…
|
||||||
|
searchable = params.searchable
|
||||||
|
detailed = True # todo: configurable?
|
||||||
|
geometry = True # todo: configurable
|
||||||
|
|
||||||
|
cache_key = 'mapdata:api:location:list:%d:%s:%d' % (
|
||||||
|
searchable + detailed*2 + geometry*4,
|
||||||
|
AccessPermission.cache_key_for_request(request),
|
||||||
|
request.user_permissions.can_access_base_mapdata
|
||||||
|
)
|
||||||
|
result = cache.get(cache_key, None)
|
||||||
|
if result is None:
|
||||||
|
if searchable:
|
||||||
|
locations = searchable_locations_for_request(request)
|
||||||
|
else:
|
||||||
|
locations = visible_locations_for_request(request).values()
|
||||||
|
|
||||||
|
result = tuple(obj.serialize(detailed=detailed, search=searchable,
|
||||||
|
geometry=geometry and can_access_geometry(request),
|
||||||
|
simple_geometry=True)
|
||||||
|
for obj in locations)
|
||||||
|
cache.set(cache_key, result, 300)
|
||||||
|
return result
|
||||||
|
|
|
@ -15,7 +15,8 @@ class SerializableSchema(Schema):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _run_root_validator(cls, values: Any, handler: ModelWrapValidatorHandler[Schema], info: ValidationInfo) -> Any:
|
def _run_root_validator(cls, values: Any, handler: ModelWrapValidatorHandler[Schema], info: ValidationInfo) -> Any:
|
||||||
""" overwriting this, we need to call serialize to get the correct data """
|
""" overwriting this, we need to call serialize to get the correct data """
|
||||||
values = values.serialize()
|
if not isinstance(values, dict):
|
||||||
|
values = values.serialize()
|
||||||
return handler(values)
|
return handler(values)
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,3 +156,24 @@ class WithSpaceSchema(SerializableSchema):
|
||||||
title="space",
|
title="space",
|
||||||
description="space id this object belongs to.",
|
description="space id this object belongs to.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleGeometryBoundsSchema(Schema):
|
||||||
|
bounds: tuple[tuple[float, float], tuple[float, float]] = APIField(
|
||||||
|
description="location bounding box from (x, y) to (x, y)",
|
||||||
|
example=((-10, -20), (20, 30)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleGeometryBoundsAndPointSchema(SimpleGeometryBoundsSchema):
|
||||||
|
point: tuple[PositiveInt, float, float] = APIField(
|
||||||
|
title="point representation of the location",
|
||||||
|
description="made from the level ID, X and Y in this order",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleGeometryLocationsSchema(Schema):
|
||||||
|
locations: list[PositiveInt] = APIField( # todo: this should be a set… but json serialization?
|
||||||
|
description="IDs of all locations that belong to this grouo",
|
||||||
|
example=(1, 2, 3),
|
||||||
|
)
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
from typing import Optional
|
from typing import Annotated, Literal, Optional, Union
|
||||||
|
|
||||||
|
from pydantic import Discriminator
|
||||||
from pydantic import Field as APIField
|
from pydantic import Field as APIField
|
||||||
from pydantic import NonNegativeFloat, PositiveFloat, PositiveInt
|
from pydantic import GetJsonSchemaHandler, NonNegativeFloat, PositiveFloat, PositiveInt
|
||||||
|
from pydantic.json_schema import JsonSchemaValue
|
||||||
|
from pydantic_core import CoreSchema
|
||||||
|
|
||||||
from c3nav.api.utils import NonEmptyStr
|
from c3nav.api.utils import NonEmptyStr
|
||||||
from c3nav.mapdata.schemas.model_base import (DjangoModelSchema, LabelSettingsSchema, LocationSchema,
|
from c3nav.mapdata.schemas.model_base import (DjangoModelSchema, LabelSettingsSchema, LocationSchema,
|
||||||
|
LocationSlugSchema, SimpleGeometryBoundsAndPointSchema,
|
||||||
|
SimpleGeometryBoundsSchema, SimpleGeometryLocationsSchema,
|
||||||
SpecificLocationSchema, TitledSchema, WithAccessRestrictionSchema,
|
SpecificLocationSchema, TitledSchema, WithAccessRestrictionSchema,
|
||||||
WithLevelSchema, WithLineStringGeometrySchema, WithPointGeometrySchema,
|
WithLevelSchema, WithLineStringGeometrySchema, WithPointGeometrySchema,
|
||||||
WithPolygonGeometrySchema, WithSpaceSchema)
|
WithPolygonGeometrySchema, WithSpaceSchema)
|
||||||
|
@ -308,3 +313,57 @@ class AccessRestrictionGroupSchema(WithAccessRestrictionSchema, DjangoModelSchem
|
||||||
For simplicity's sake, access restrictions can belong to groups, and you can grant permissions for the entire group.
|
For simplicity's sake, access restrictions can belong to groups, and you can grant permissions for the entire group.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TypedLevelSchema(LevelSchema):
|
||||||
|
"""
|
||||||
|
A level for the location API.
|
||||||
|
See Level schema for details.
|
||||||
|
"""
|
||||||
|
locationtype: Literal["level"]
|
||||||
|
|
||||||
|
|
||||||
|
class TypedSpaceSchema(SimpleGeometryBoundsAndPointSchema, SpaceSchema):
|
||||||
|
"""
|
||||||
|
A space with some additional information for the location API.
|
||||||
|
See Space schema for details.
|
||||||
|
"""
|
||||||
|
locationtype: Literal["space"]
|
||||||
|
|
||||||
|
|
||||||
|
class TypedAreaSchema(SimpleGeometryBoundsAndPointSchema, AreaSchema):
|
||||||
|
"""
|
||||||
|
An area with some additional information for the location API.
|
||||||
|
See Area schema for details.
|
||||||
|
"""
|
||||||
|
locationtype: Literal["area"]
|
||||||
|
|
||||||
|
|
||||||
|
class TypedPOISchema(SimpleGeometryBoundsSchema, POISchema):
|
||||||
|
"""
|
||||||
|
A point of interest with some additional information for the location API.
|
||||||
|
See POI schema for details.
|
||||||
|
"""
|
||||||
|
locationtype: Literal["poi"]
|
||||||
|
|
||||||
|
|
||||||
|
class TypedLocationGroupSchema(SimpleGeometryLocationsSchema, LocationGroupSchema):
|
||||||
|
"""
|
||||||
|
A locagroun group with some additional information for the location API.
|
||||||
|
See LocationGroup schema for details.
|
||||||
|
"""
|
||||||
|
locationtype: Literal["locationgroup"]
|
||||||
|
|
||||||
|
|
||||||
|
AnyLocationSchema = Annotated[
|
||||||
|
Union[
|
||||||
|
TypedLevelSchema,
|
||||||
|
TypedSpaceSchema,
|
||||||
|
TypedAreaSchema,
|
||||||
|
TypedPOISchema,
|
||||||
|
TypedLocationGroupSchema,
|
||||||
|
],
|
||||||
|
Discriminator("locationtype"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue