integrate data overlay api into new MapdataAPIBuilder
This commit is contained in:
parent
be76f3a8db
commit
707c81f159
5 changed files with 38 additions and 41 deletions
|
@ -17,7 +17,7 @@ from c3nav.mapdata.models.geometry.space import (POI, Column, CrossDescription,
|
|||
Obstacle, Ramp)
|
||||
from c3nav.mapdata.models.locations import DynamicLocation
|
||||
from c3nav.mapdata.schemas.filters import (ByCategoryFilter, ByGroupFilter, ByOnTopOfFilter, FilterSchema,
|
||||
LevelGeometryFilter, SpaceGeometryFilter, BySpaceFilter)
|
||||
LevelGeometryFilter, SpaceGeometryFilter, BySpaceFilter, ByOverlayFilter)
|
||||
from c3nav.mapdata.schemas.model_base import schema_description
|
||||
from c3nav.mapdata.schemas.models import (AccessRestrictionGroupSchema, AccessRestrictionSchema, AreaSchema,
|
||||
BuildingSchema, ColumnSchema, CrossDescriptionSchema, DoorSchema,
|
||||
|
@ -143,6 +143,7 @@ class MapdataAPIBuilder:
|
|||
call_func=mapdata_retrieve_endpoint,
|
||||
add_call_params={"model": endpoint.model.__name__, "pk": id_field}
|
||||
)
|
||||
list_func.__name__ = f"{endpoint.model_name}_by_id"
|
||||
|
||||
self.router.get(f'/{endpoint.model_name_plural}/{{{id_field}}}/', summary=f"{endpoint.model_name} by ID",
|
||||
tags=[f"mapdata-{tag}"], description=schema_description(endpoint.schema),
|
||||
|
@ -195,6 +196,15 @@ mapdata_endpoints: dict[str, list[MapdataEndpoint]] = {
|
|||
model=DynamicLocation,
|
||||
schema=DynamicLocationSchema,
|
||||
),
|
||||
MapdataEndpoint(
|
||||
model=DataOverlay,
|
||||
schema=DataOverlaySchema,
|
||||
),
|
||||
MapdataEndpoint(
|
||||
model=DataOverlayFeature,
|
||||
schema=DataOverlayFeatureSchema,
|
||||
filters=ByOverlayFilter,
|
||||
),
|
||||
],
|
||||
"level": [
|
||||
MapdataEndpoint(
|
||||
|
@ -269,35 +279,3 @@ mapdata_endpoints: dict[str, list[MapdataEndpoint]] = {
|
|||
|
||||
|
||||
MapdataAPIBuilder(router=mapdata_api_router).build_all_endpoints(mapdata_endpoints)
|
||||
|
||||
|
||||
"""
|
||||
Data overlays
|
||||
"""
|
||||
|
||||
|
||||
# todo: this wants to move into a MapDataEndpoint
|
||||
@mapdata_api_router.get('/overlays/', summary="data overlay list",
|
||||
tags=["mapdata-root"], description=schema_description(DynamicLocationSchema),
|
||||
response={200: list[DataOverlaySchema], **auth_responses})
|
||||
@api_etag()
|
||||
def dataoverlay_list(request):
|
||||
return mapdata_list_endpoint(request, model=DataOverlay)
|
||||
|
||||
|
||||
# todo: this wants to move into a MapDataEndpoint
|
||||
@mapdata_api_router.get('/overlays/{overlay_id}/', summary="features for overlay by overlay ID",
|
||||
tags=["mapdata-root"], description=schema_description(DynamicLocationSchema),
|
||||
response={200: list[DataOverlayFeatureSchema], **API404.dict(), **auth_responses})
|
||||
# @api_etag()
|
||||
def dataoverlay_by_id(request, overlay_id: int):
|
||||
qs = optimize_query(
|
||||
DataOverlayFeature.qs_for_request(request)
|
||||
)
|
||||
|
||||
qs = qs.filter(overlay_id=overlay_id)
|
||||
|
||||
# order_by
|
||||
qs = qs.order_by('pk')
|
||||
|
||||
return qs
|
||||
|
|
|
@ -21,11 +21,11 @@ class DataOverlay(TitledMixin, models.Model):
|
|||
verbose_name=_('headers for pull http request (JSON object)'))
|
||||
pull_interval = models.DurationField(blank=True, null=True, verbose_name=_('pull interval'))
|
||||
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Data Overlay')
|
||||
verbose_name_plural = _('Data Overlays')
|
||||
default_related_name = 'data_overlays'
|
||||
default_related_name = 'dataoverlays'
|
||||
|
||||
|
||||
class DataOverlayFeature(TitledMixin, GeometryMixin, models.Model):
|
||||
overlay = models.ForeignKey('mapdata.DataOverlay', on_delete=models.CASCADE, verbose_name=_('Overlay'), related_name='features')
|
||||
|
@ -45,7 +45,6 @@ class DataOverlayFeature(TitledMixin, GeometryMixin, models.Model):
|
|||
extra_data: Optional[dict[str, str]] = SchemaField(schema=dict[str, str], blank=True, null=True, default=None,
|
||||
verbose_name=_('extra data (JSON object)'))
|
||||
|
||||
|
||||
def to_geojson(self, instance=None) -> dict:
|
||||
result = {
|
||||
'type': 'Feature',
|
||||
|
@ -65,7 +64,6 @@ class DataOverlayFeature(TitledMixin, GeometryMixin, models.Model):
|
|||
def get_geojson_key(self):
|
||||
return 'dataoverlayfeature', self.id
|
||||
|
||||
|
||||
def _serialize(self, **kwargs):
|
||||
result = super()._serialize(**kwargs)
|
||||
result.update({
|
||||
|
@ -84,4 +82,4 @@ class DataOverlayFeature(TitledMixin, GeometryMixin, models.Model):
|
|||
return result
|
||||
|
||||
class Meta:
|
||||
default_related_name = "overlayfeatures"
|
||||
default_related_name = "dataoverlayfeatures"
|
||||
|
|
|
@ -136,6 +136,23 @@ class ByOnTopOfFilter(FilterSchema):
|
|||
return super().filter_qs(qs)
|
||||
|
||||
|
||||
class ByOverlayFilter(FilterSchema):
|
||||
overlay: int = APIField(
|
||||
title='filter by data overlay',
|
||||
description='only show overlay features belonging to this overlay'
|
||||
)
|
||||
|
||||
def validate(self, request):
|
||||
super().validate(request)
|
||||
if self.overlay is not None:
|
||||
assert_valid_value(request, Level, "pk", {self.overlay})
|
||||
|
||||
def filter_qs(self, qs: QuerySet) -> QuerySet:
|
||||
if self.overlay is not None:
|
||||
qs = qs.filter(overlay=self.overlay)
|
||||
return super().filter_qs(qs)
|
||||
|
||||
|
||||
class BySearchableFilter(FilterSchema):
|
||||
searchable: bool = APIField(
|
||||
False,
|
||||
|
|
|
@ -319,11 +319,16 @@ class DynamicLocationSchema(SpecificLocationSchema, DjangoModelSchema):
|
|||
|
||||
|
||||
class DataOverlaySchema(TitledSchema, DjangoModelSchema):
|
||||
# TODO
|
||||
"""
|
||||
Represents a collection of geometries to be displayed as an optional overlay to the map.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class DataOverlayFeatureSchema(TitledSchema, DjangoModelSchema):
|
||||
"""
|
||||
A feature (any kind of geometry) to be displayed as part of a data overlay.
|
||||
"""
|
||||
geometry: AnyGeometrySchema
|
||||
level_id: PositiveInt
|
||||
stroke_color: Optional[str]
|
||||
|
@ -336,7 +341,6 @@ class DataOverlayFeatureSchema(TitledSchema, DjangoModelSchema):
|
|||
external_url: Optional[str]
|
||||
extra_data: Optional[dict[str, str]]
|
||||
# TODO
|
||||
pass
|
||||
|
||||
|
||||
class SourceSchema(WithAccessRestrictionSchema, DjangoModelSchema):
|
||||
|
|
|
@ -2841,7 +2841,7 @@ class DataOverlay {
|
|||
}
|
||||
|
||||
async create() {
|
||||
const features = await c3nav_api.get(`mapdata/overlays/${this.id}/`);
|
||||
const features = await c3nav_api.get(`mapdata/dataoverlayfeatures/?overlay=${this.id}`);
|
||||
|
||||
const levels = {};
|
||||
for (const feature of features) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue