Fix api stores
Rename in category table: geom_type to gis_type
This commit is contained in:
parent
c0c308a657
commit
956147aea8
7 changed files with 45 additions and 22 deletions
|
@ -6,7 +6,6 @@ from fastapi import Depends, FastAPI, HTTPException, status, responses
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
from fastapi.security import OAuth2PasswordRequestForm
|
from fastapi.security import OAuth2PasswordRequestForm
|
||||||
from sqlmodel import select
|
from sqlmodel import select
|
||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
||||||
|
|
||||||
from gisaf.models.authentication import (
|
from gisaf.models.authentication import (
|
||||||
User, UserRead,
|
User, UserRead,
|
||||||
|
@ -105,7 +104,8 @@ async def get_categories_p(
|
||||||
|
|
||||||
@api.get("/stores")
|
@api.get("/stores")
|
||||||
async def get_stores() -> list[Store]:
|
async def get_stores() -> list[Store]:
|
||||||
df = registry.stores.reset_index().drop(columns=['model', 'raw_model'])
|
df = registry.stores.reset_index().\
|
||||||
|
drop(columns=['model', 'raw_model', 'base_gis_type'])
|
||||||
return df.to_dict(orient="records")
|
return df.to_dict(orient="records")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ class RawSurveyImporter(Importer):
|
||||||
gdf['geom'] = gdf.to_crs(conf.srid).geometry.apply(lambda g: dumps_wkb(g, srid=conf.srid, hex=True))
|
gdf['geom'] = gdf.to_crs(conf.srid).geometry.apply(lambda g: dumps_wkb(g, srid=conf.srid, hex=True))
|
||||||
for category_name, category_gdf in gdf.groupby('category'):
|
for category_name, category_gdf in gdf.groupby('category'):
|
||||||
category = registry.categories.loc[category_name]
|
category = registry.categories.loc[category_name]
|
||||||
if category.auto_import and category.geom_type == 'Point':
|
if category.auto_import and category.gis_type == 'Point':
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
await upsert_df(category_gdf, category.model)
|
await upsert_df(category_gdf, category.model)
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ class GeoDataImporter(Importer):
|
||||||
await upsert_df(new_tags, Tags)
|
await upsert_df(new_tags, Tags)
|
||||||
|
|
||||||
## Publish on Gisaf live
|
## Publish on Gisaf live
|
||||||
gis_type = gdf_file.geom_type.iloc[0]
|
gis_type = gdf_file.gis_type.iloc[0]
|
||||||
mapbox_type = SHAPELY_TYPE_TO_MAPBOX_TYPE.get(gis_type, None)
|
mapbox_type = SHAPELY_TYPE_TO_MAPBOX_TYPE.get(gis_type, None)
|
||||||
mapbox_paint = DEFAULT_MAPBOX_PAINT.get(mapbox_type, {}).copy()
|
mapbox_paint = DEFAULT_MAPBOX_PAINT.get(mapbox_type, {}).copy()
|
||||||
mapbox_layout = DEFAULT_MAPBOX_LAYOUT.get(mapbox_type, {}).copy()
|
mapbox_layout = DEFAULT_MAPBOX_LAYOUT.get(mapbox_type, {}).copy()
|
||||||
|
|
|
@ -60,9 +60,9 @@ class CategoryBase(BaseModel):
|
||||||
status: str = Field(min_length=1, max_length=1)
|
status: str = Field(min_length=1, max_length=1)
|
||||||
custom: bool | None
|
custom: bool | None
|
||||||
auto_import: bool = True
|
auto_import: bool = True
|
||||||
geom_type: str = Field(max_length=50,
|
gis_type: str = Field(max_length=50,
|
||||||
foreign_key='category_model_type.name',
|
foreign_key='category_model_type.name',
|
||||||
default='Point')
|
default='Point')
|
||||||
long_name: str | None = Field(max_length=50)
|
long_name: str | None = Field(max_length=50)
|
||||||
style: str | None = Field(sa_type=TEXT)
|
style: str | None = Field(sa_type=TEXT)
|
||||||
symbol: str | None = Field(max_length=1)
|
symbol: str | None = Field(max_length=1)
|
||||||
|
@ -108,7 +108,7 @@ class CategoryBase(BaseModel):
|
||||||
@computed_field
|
@computed_field
|
||||||
@property
|
@property
|
||||||
def mapbox_type(self) -> str:
|
def mapbox_type(self) -> str:
|
||||||
return self.mapbox_type_custom or mapbox_type_mapping[self.geom_type]
|
return self.mapbox_type_custom or mapbox_type_mapping[self.gis_type]
|
||||||
|
|
||||||
|
|
||||||
class Category(CategoryBase, table=True):
|
class Category(CategoryBase, table=True):
|
||||||
|
|
|
@ -287,6 +287,9 @@ class GeoModel(Model):
|
||||||
Base class for all geo models
|
Base class for all geo models
|
||||||
"""
|
"""
|
||||||
#__abstract__ = True
|
#__abstract__ = True
|
||||||
|
|
||||||
|
id: int | None = Field(default=None, primary_key=True)
|
||||||
|
|
||||||
description: ClassVar[str] = ''
|
description: ClassVar[str] = ''
|
||||||
attribution: ClassVar[str | None] = None
|
attribution: ClassVar[str | None] = None
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class MapLibreStyle(BaseModel):
|
||||||
|
|
||||||
class Store(BaseModel):
|
class Store(BaseModel):
|
||||||
auto_import: bool
|
auto_import: bool
|
||||||
base_gis_type: str
|
# base_gis_type: str
|
||||||
count: int
|
count: int
|
||||||
custom: bool
|
custom: bool
|
||||||
description: str
|
description: str
|
||||||
|
@ -23,12 +23,12 @@ class Store(BaseModel):
|
||||||
#mapbox_layout: dict[str, Any] | None
|
#mapbox_layout: dict[str, Any] | None
|
||||||
#mapbox_paint: dict[str, Any] | None
|
#mapbox_paint: dict[str, Any] | None
|
||||||
#mapbox_type: str
|
#mapbox_type: str
|
||||||
mapbox_type_custom: str | None
|
# mapbox_type_custom: str | None
|
||||||
#mapbox_type_default: str
|
#mapbox_type_default: str
|
||||||
minor_group_1: str
|
minor_group_1: str | None
|
||||||
minor_group_2: str
|
minor_group_2: str | None
|
||||||
#model: GeoModel
|
#model: GeoModel
|
||||||
geom_type: str
|
gis_type: str
|
||||||
name: str
|
name: str
|
||||||
#name_letter: str
|
#name_letter: str
|
||||||
#name_number: int
|
#name_number: int
|
||||||
|
|
|
@ -190,7 +190,7 @@ class Store:
|
||||||
gdf['popup'] = 'Live: ' + live_name + ' #' + gdf.index.astype('U')
|
gdf['popup'] = 'Live: ' + live_name + ' #' + gdf.index.astype('U')
|
||||||
if len(gdf) > 0:
|
if len(gdf) > 0:
|
||||||
gdf = gdf.to_crs(conf.crs.geojson)
|
gdf = gdf.to_crs(conf.crs.geojson)
|
||||||
gis_type = gdf.geom_type.iloc[0]
|
gis_type = gdf.gis_type.iloc[0]
|
||||||
else:
|
else:
|
||||||
gis_type = 'Point' ## FIXME: cannot be inferred from the gdf?
|
gis_type = 'Point' ## FIXME: cannot be inferred from the gdf?
|
||||||
mapbox_type = SHAPELY_TYPE_TO_MAPBOX_TYPE.get(gis_type, None)
|
mapbox_type = SHAPELY_TYPE_TO_MAPBOX_TYPE.get(gis_type, None)
|
||||||
|
|
|
@ -14,6 +14,7 @@ from sqlalchemy import text
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
from sqlmodel import SQLModel, select, inspect
|
from sqlmodel import SQLModel, select, inspect
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from gisaf.config import conf
|
from gisaf.config import conf
|
||||||
from gisaf.models import (misc, category as category_module,
|
from gisaf.models import (misc, category as category_module,
|
||||||
|
@ -166,7 +167,7 @@ class ModelRegistry:
|
||||||
else:
|
else:
|
||||||
logger.debug('Discovered {:s}'.format(category.raw_survey_table_name))
|
logger.debug('Discovered {:s}'.format(category.raw_survey_table_name))
|
||||||
|
|
||||||
model_class = category_model_mapper.get(category.geom_type)
|
model_class = category_model_mapper.get(category.gis_type)
|
||||||
## Final geometries
|
## Final geometries
|
||||||
try:
|
try:
|
||||||
if model_class:
|
if model_class:
|
||||||
|
@ -213,13 +214,13 @@ class ModelRegistry:
|
||||||
obj = getattr(module, name)
|
obj = getattr(module, name)
|
||||||
if hasattr(obj, '__module__') and obj.__module__.startswith(module.__name__)\
|
if hasattr(obj, '__module__') and obj.__module__.startswith(module.__name__)\
|
||||||
and hasattr(obj, '__tablename__') and hasattr(obj, 'get_store_name'):
|
and hasattr(obj, '__tablename__') and hasattr(obj, 'get_store_name'):
|
||||||
geom_type = self.add_model(obj)
|
gis_type = self.add_model(obj)
|
||||||
logger.debug(f'Model {obj.get_store_name()} added in the registry from gisaf source tree as {geom_type}')
|
logger.debug(f'Model {obj.get_store_name()} added in the registry from gisaf source tree as {gis_type}')
|
||||||
|
|
||||||
## Scan the models defined in plugins (setuptools' entry points)
|
## Scan the models defined in plugins (setuptools' entry points)
|
||||||
for module_name, model in self.scan_entry_points(name='gisaf_extras.models').items():
|
for module_name, model in self.scan_entry_points(name='gisaf_extras.models').items():
|
||||||
geom_type = self.add_model(model)
|
gis_type = self.add_model(model)
|
||||||
logger.debug(f'Model {model.get_store_name()} added in the registry from {module_name} entry point as {geom_type}')
|
logger.debug(f'Model {model.get_store_name()} added in the registry from {module_name} entry point as {gis_type}')
|
||||||
|
|
||||||
for module_name, store in self.scan_entry_points(name='gisaf_extras.stores').items():
|
for module_name, store in self.scan_entry_points(name='gisaf_extras.stores').items():
|
||||||
self.add_store(store)
|
self.add_store(store)
|
||||||
|
@ -362,11 +363,15 @@ class ModelRegistry:
|
||||||
Used in GraphQl queries.
|
Used in GraphQl queries.
|
||||||
"""
|
"""
|
||||||
## Utility functions used with apply method (dataframes)
|
## Utility functions used with apply method (dataframes)
|
||||||
def fill_columns_from_custom_models(row) -> tuple[str, str, str]:
|
def fill_columns_from_custom_models(row) -> tuple[str, str, str, str, str, str, str]:
|
||||||
return (
|
return (
|
||||||
|
row.model.__name__,
|
||||||
row.model.__name__,
|
row.model.__name__,
|
||||||
row.model.description,
|
row.model.description,
|
||||||
row.model.metadata.schema
|
row.model.metadata.schema,
|
||||||
|
row.model.base_gis_type,
|
||||||
|
row.model.style,
|
||||||
|
row.model.symbol,
|
||||||
)
|
)
|
||||||
|
|
||||||
def fill_columns_from_custom_stores(row) -> tuple[str, str, None]:
|
def fill_columns_from_custom_stores(row) -> tuple[str, str, None]:
|
||||||
|
@ -430,7 +435,9 @@ class ModelRegistry:
|
||||||
self.categories['is_line_work'] = None
|
self.categories['is_line_work'] = None
|
||||||
self.categories['raw_survey_model'] = None
|
self.categories['raw_survey_model'] = None
|
||||||
|
|
||||||
|
## --------------------
|
||||||
## Custom models (Misc)
|
## Custom models (Misc)
|
||||||
|
## --------------------
|
||||||
self.custom_models = pd.DataFrame(
|
self.custom_models = pd.DataFrame(
|
||||||
self.geom_custom.items(),
|
self.geom_custom.items(),
|
||||||
columns=['store', 'model']
|
columns=['store', 'model']
|
||||||
|
@ -446,17 +453,27 @@ class ModelRegistry:
|
||||||
self.custom_models = self.custom_models.loc[self.custom_models.in_menu]
|
self.custom_models = self.custom_models.loc[self.custom_models.in_menu]
|
||||||
self.custom_models['auto_import'] = False
|
self.custom_models['auto_import'] = False
|
||||||
self.custom_models['is_line_work'] = False
|
self.custom_models['is_line_work'] = False
|
||||||
|
self.custom_models['minor_group_1'] = None
|
||||||
|
self.custom_models['minor_group_2'] = None
|
||||||
|
|
||||||
if len(self.custom_models) > 0:
|
if len(self.custom_models) > 0:
|
||||||
|
self.custom_models['name'],\
|
||||||
self.custom_models['long_name'],\
|
self.custom_models['long_name'],\
|
||||||
self.custom_models['custom_description'],\
|
self.custom_models['custom_description'],\
|
||||||
self.custom_models['db_schema'],\
|
self.custom_models['db_schema'],\
|
||||||
|
self.custom_models['gis_type'],\
|
||||||
|
self.custom_models['style'],\
|
||||||
|
self.custom_models['symbol'],\
|
||||||
= zip(*self.custom_models.apply(fill_columns_from_custom_models, axis=1))
|
= zip(*self.custom_models.apply(fill_columns_from_custom_models, axis=1))
|
||||||
## Try to give a meaningful description, eg. including the source (db_schema)
|
## Try to give a meaningful description, eg. including the source (db_schema)
|
||||||
self.custom_models['description'] = self.custom_models['custom_description'].fillna(self.custom_models['long_name'] + '-' + self.custom_models['db_schema'])
|
self.custom_models['description'] = self.custom_models['custom_description'].fillna(self.custom_models['long_name'] + '-' + self.custom_models['db_schema'])
|
||||||
self.custom_models['title'] = self.custom_models['long_name']
|
self.custom_models['title'] = self.custom_models['long_name']
|
||||||
|
self.custom_models.fillna(np.nan, inplace=True)
|
||||||
|
self.custom_models.replace([np.nan], [None], inplace=True)
|
||||||
|
|
||||||
|
## -------------------------
|
||||||
## Custom stores (Community)
|
## Custom stores (Community)
|
||||||
|
## -------------------------
|
||||||
self.custom_stores = pd.DataFrame(
|
self.custom_stores = pd.DataFrame(
|
||||||
self.geom_custom_store.items(),
|
self.geom_custom_store.items(),
|
||||||
columns=['store', 'model']
|
columns=['store', 'model']
|
||||||
|
@ -481,6 +498,8 @@ class ModelRegistry:
|
||||||
self.custom_stores['db_schema'],\
|
self.custom_stores['db_schema'],\
|
||||||
= zip(*self.custom_stores.apply(fill_columns_from_custom_stores, axis=1))
|
= zip(*self.custom_stores.apply(fill_columns_from_custom_stores, axis=1))
|
||||||
self.custom_stores['title'] = self.custom_stores['long_name']
|
self.custom_stores['title'] = self.custom_stores['long_name']
|
||||||
|
self.custom_stores.fillna(np.nan, inplace=True)
|
||||||
|
self.custom_stores.replace([np.nan], [None], inplace=True)
|
||||||
|
|
||||||
## Combine Misc (custom) and survey (auto) stores
|
## Combine Misc (custom) and survey (auto) stores
|
||||||
## Retain only one status per category (defaultStatus, 'E'/existing by default)
|
## Retain only one status per category (defaultStatus, 'E'/existing by default)
|
||||||
|
@ -490,6 +509,7 @@ class ModelRegistry:
|
||||||
self.custom_stores
|
self.custom_stores
|
||||||
])#.drop(columns=['store_name'])
|
])#.drop(columns=['store_name'])
|
||||||
self.stores['in_menu'] = self.stores['in_menu'].astype(bool)
|
self.stores['in_menu'] = self.stores['in_menu'].astype(bool)
|
||||||
|
self.stores['status'].fillna('E', inplace=True)
|
||||||
|
|
||||||
## Set in the stores dataframe some useful properties, from the model class
|
## Set in the stores dataframe some useful properties, from the model class
|
||||||
## Maybe at some point it makes sense to get away from class-based definitions
|
## Maybe at some point it makes sense to get away from class-based definitions
|
||||||
|
@ -621,7 +641,7 @@ class ModelRegistry:
|
||||||
columns={
|
columns={
|
||||||
'live': 'is_live',
|
'live': 'is_live',
|
||||||
'zIndex': 'z_index',
|
'zIndex': 'z_index',
|
||||||
'gisType': 'geom_type',
|
'gisType': 'gis_type',
|
||||||
# 'type': 'mapbox_type',
|
# 'type': 'mapbox_type',
|
||||||
'viewableRole': 'viewable_role',
|
'viewableRole': 'viewable_role',
|
||||||
}, inplace=True
|
}, inplace=True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue