diff --git a/src/gisaf/api.py b/src/gisaf/api.py index 86bccc8..c3c0e87 100644 --- a/src/gisaf/api.py +++ b/src/gisaf/api.py @@ -13,6 +13,7 @@ from gisaf.models.authentication import ( Role, RoleRead, ) from gisaf.models.category import Category, CategoryRead +from gisaf.models.to_migrate import DataProvider from gisaf.config import conf from gisaf.models.bootstrap import BootstrapData from gisaf.models.store import Store @@ -58,13 +59,16 @@ async def login_for_access_token( return Token(access_token=access_token, token_type='bearer') @api.get("/list") -async def list_data_providers(): +async def list_data_providers() -> list[DataProvider]: """ Return a list of data providers, for use with the api (graphs, etc) :return: """ - return [{'name': m.__name__, 'store': m.get_store_name()} - for m in registry.values_for_model] + return [ + DataProvider( + name=model.get_store_name(), + values=[value.get_store_name() for value in values] + ) for model, values in registry.values_for_model.items()] @api.get("/users") diff --git a/src/gisaf/models/to_migrate.py b/src/gisaf/models/to_migrate.py index 13c34ac..aa92c5b 100644 --- a/src/gisaf/models/to_migrate.py +++ b/src/gisaf/models/to_migrate.py @@ -16,3 +16,7 @@ class ModelAction(BaseModel): name: str icon: str formFields: list[FormField] + +class DataProvider(BaseModel): + name: str + values: list[str] \ No newline at end of file diff --git a/src/gisaf/plugins.py b/src/gisaf/plugins.py index 00660a3..464ce11 100644 --- a/src/gisaf/plugins.py +++ b/src/gisaf/plugins.py @@ -120,9 +120,12 @@ class DownloadPlugin: class DownloadCSVPlugin(DownloadPlugin): async def execute(self, model, item, request): from gisaf.registry import registry - values_model = registry.values_for_model.get(model) - df = await values_model.get_as_dataframe(model_id=item.id) - csv = df.to_csv(date_format='%d/%m/%Y %H:%M', float_format=values_model.float_format) + values_models = registry.values_for_model.get(model) + for value_model in values_models: + df = await values_models.get_as_dataframe(model_id=item.id) + csv = df.to_csv(date_format='%d/%m/%Y %H:%M', float_format=value_model.float_format) + ## TODO: implement multiple values for a model (search for values_for_model) + break return { 'file_name': '{:s}.csv'.format(item.caption), 'content_type': 'text/csv', diff --git a/src/gisaf/registry.py b/src/gisaf/registry.py index fca7bbd..97c5411 100644 --- a/src/gisaf/registry.py +++ b/src/gisaf/registry.py @@ -6,13 +6,13 @@ import importlib import pkgutil from collections import defaultdict from importlib.metadata import entry_points -from typing import Any, ClassVar +from typing import Any, ClassVar, Literal from pydantic import create_model from pydantic_core import PydanticUndefined from sqlalchemy import text from sqlalchemy.orm import selectinload -from sqlmodel import SQLModel, select +from sqlmodel import SQLModel, select, inspect import pandas as pd from gisaf.config import conf @@ -83,6 +83,8 @@ class ModelRegistry: misc: dict[str, SQLModel] raw_survey_models: dict[str, RawSurveyBaseModel] survey_models: dict[str, SurveyModel] + ## TODO: implement multiple values for a model (search for values_for_model) + values_for_model: dict[GeoModel, list[PlottableModel]] def __init__(self) -> None: """ @@ -261,17 +263,13 @@ class ModelRegistry: ''' Build a dict for quick access to the values from a model ''' - logger.warning(ToMigrate('populate_values_for_model')) - return self.values_for_model = {} for model_value in self.values.values(): - for field in model_value.model_fields.values(): - foreign_key = getattr(field, 'foreign_key', False) - if foreign_key and foreign_key is not PydanticUndefined: - breakpoint() - model = ... - self.values_for_model[model] = model_value - + for relationship in inspect(model_value).relationships: + model = self.stores.loc[relationship.target.fullname, 'model'] + if model not in self.values_for_model: + self.values_for_model[model] = [] + self.values_for_model[model].append(model_value) def scan_entry_points(self, name): """ @@ -286,15 +284,15 @@ class ModelRegistry: logger.warning(err) return named_objects - def add_model(self, model) -> str: + def add_model(self, model) -> Literal['GeoModel', 'PlottableModel', 'Other model']: """ - Add the model - :return: Model type (one of {'GeoModel', 'PlottableModel', 'Other model'}) + Add the model to its proper dict for reference, return the type """ # if not hasattr(model, 'get_store_name'): # raise NotInRegistry() table_name = model.get_store_name() - if issubclass(model, GeoModel) and not issubclass(model, RawSurveyBaseModel) and not model.hidden: + if issubclass(model, GeoModel) and not \ + issubclass(model, RawSurveyBaseModel) and not model.hidden: self.geom_custom[table_name] = model return 'GeoModel' elif issubclass(model, PlottableModel): @@ -358,19 +356,6 @@ class ModelRegistry: resp['externalRecordUrl'] = item.get_external_record_url() return resp - def get_other_model_from_table_name(self, table_name): - """ - Utility func to get a non-geom model from a table name - :param table_name: str - :return: model or None - """ - for model in registry.other.values(): - if model.__tablename__ == table_name: - return model - for model in registry.values.values(): - if model.__tablename__ == table_name: - return model - async def make_stores(self): """ Make registry for primary groups, categories and survey stores using Pandas dataframes.