diff --git a/backend/gncitizen/core/sites/admin.py b/backend/gncitizen/core/sites/admin.py index 36a2f1ea..e0df00a2 100644 --- a/backend/gncitizen/core/sites/admin.py +++ b/backend/gncitizen/core/sites/admin.py @@ -1,4 +1,64 @@ +from flask_admin.actions import action from flask_admin.contrib.sqla.view import ModelView +from gncitizen.utils.admin import CustomJSONField, CustomTileView, json_formatter +from server import db +from wtforms import SelectField + +from .models import SiteModel, VisitModel + + +def enum_formatter(view, context, model, name): + enum_attr = getattr(model, name) + return enum_attr.value + + +class SiteView(CustomTileView): + can_export = True + inline_models = [ + VisitModel, + ] + # column_exclude_list = ["geom"] + column_list = [ + "id_site", + "name", + "visits", + "site_type.type", + "id_program", + "program.title", + "geom", + ] + column_filters = ( + "name", + "site_type.type", + "id_program", + "program.title", + "program.unique_id_program", + ) + column_searchable_list = ( + "name", + "site_type.type", + "id_program", + "program.title", + "program.unique_id_program", + ) + can_create = False + + +class VisitView(CustomTileView): + can_export = True + form_overrides = {"json_data": CustomJSONField} + column_formatters = { + "json_data": json_formatter, + } + # column_exclude_list = ["geom"] + column_filters = ( + "date", + "site.site_type.type", + "site.id_program", + "site.program.title", + "site.program.unique_id_program", + ) + can_create = False class SiteTypeView(ModelView): diff --git a/backend/gncitizen/core/sites/models.py b/backend/gncitizen/core/sites/models.py index b7ec5191..a4acee15 100644 --- a/backend/gncitizen/core/sites/models.py +++ b/backend/gncitizen/core/sites/models.py @@ -3,10 +3,6 @@ # import enum from geoalchemy2 import Geometry -from sqlalchemy.dialects.postgresql import JSONB, UUID -from sqlalchemy.orm import relationship -from utils_flask_sqla_geo.serializers import geoserializable, serializable - from gncitizen.core.commons.models import ( CustomFormModel, MediaModel, @@ -16,6 +12,9 @@ from gncitizen.core.observations.models import ObservationModel from gncitizen.core.users.models import ObserverMixinModel from server import db +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import relationship +from utils_flask_sqla_geo.serializers import geoserializable, serializable def create_schema(db): @@ -69,7 +68,7 @@ class SiteModel(TimestampMixinModel, ObserverMixinModel, db.Model): ) def __repr__(self): - return "".format(self.id_site) + return f"Site #{self.id_site} - {self.name}" @serializable @@ -97,12 +96,12 @@ class VisitModel(TimestampMixinModel, ObserverMixinModel, db.Model): id_site = db.Column( db.Integer, db.ForeignKey(SiteModel.id_site, ondelete="CASCADE"), index=True ) - site = relationship("SiteModel") + site = db.relationship("SiteModel", backref=db.backref("visits")) date = db.Column(db.Date) json_data = db.Column(JSONB, nullable=True) def __repr__(self): - return "".format(self.id_visit) + return f"Visit #{self.id_visit}" class MediaOnVisitModel(TimestampMixinModel, db.Model): diff --git a/backend/gncitizen/core/sites/routes.py b/backend/gncitizen/core/sites/routes.py index e7231f7b..714e1286 100644 --- a/backend/gncitizen/core/sites/routes.py +++ b/backend/gncitizen/core/sites/routes.py @@ -7,22 +7,26 @@ from flask_jwt_extended import jwt_required from geoalchemy2.shape import from_shape from geojson import FeatureCollection -from shapely.geometry import Point, asShape -from sqlalchemy import or_ -from utils_flask_sqla.response import json_resp -from utils_flask_sqla_geo.generic import get_geojson_feature - from gncitizen.core.commons.models import MediaModel, ProgramsModel from gncitizen.core.users.models import UserModel +from gncitizen.utils.env import admin from gncitizen.utils.errors import GeonatureApiError from gncitizen.utils.jwt import get_id_role_if_exists, get_user_if_exists from gncitizen.utils.media import save_upload_files from server import db +from shapely.geometry import Point, asShape +from sqlalchemy import or_ +from utils_flask_sqla.response import json_resp +from utils_flask_sqla_geo.generic import get_geojson_feature +from .admin import SiteView, VisitView from .models import MediaOnVisitModel, SiteModel, SiteTypeModel, VisitModel sites_api = Blueprint("sites", __name__) +admin.add_view(SiteView(SiteModel, db.session, "Sites", category="Sites")) +admin.add_view(VisitView(VisitModel, db.session, "Visites", category="Sites")) + @sites_api.route("/types", methods=["GET"]) @json_resp