Skip to content

Commit 3a4fd1a

Browse files
authored
Merge pull request #72 from PnX-SI/develop
Merge develop branch into main
2 parents 6baf6d5 + eaa163a commit 3a4fd1a

File tree

126 files changed

+2194
-5944
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+2194
-5944
lines changed

backend/gn_module_zh/blueprint.py

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
from geonature.utils.env import DB, ROOT_DIR, BACKEND_DIR
2222
from pypnnomenclature.models import TNomenclatures
2323
from pypnusershub.db.models import Organisme, User
24-
from sqlalchemy import desc, func, text
24+
from sqlalchemy import desc, func, text, select, update, delete
2525
from sqlalchemy.orm import aliased
2626
from utils_flask_sqla.generic import GenericQuery
2727
from utils_flask_sqla.response import json_resp_accept_empty_list, json_resp
2828

2929
from .api_error import ZHApiError
30+
from . import tasks # noqa: F401
3031
from .forms import (
3132
create_zh,
3233
post_file_info,
@@ -81,6 +82,7 @@
8182
get_main_picture_id,
8283
get_user_cruved,
8384
)
85+
import gn_module_zh.tasks
8486

8587
blueprint = Blueprint("pr_zh", __name__, "./static", template_folder="templates")
8688

@@ -93,7 +95,7 @@ def get_zh(scope):
9395
coauthor = aliased(User, name="coauthor")
9496
coorganism = aliased(Organisme, name="coorganism")
9597
q = (
96-
DB.session.query(TZH)
98+
select(TZH)
9799
.join(TNomenclatures, TZH.sdage)
98100
.join(User, TZH.authors)
99101
.join(coauthor, TZH.coauthors)
@@ -109,6 +111,7 @@ def get_zh(scope):
109111

110112
if request.is_json:
111113
q = main_search(q, request.json)
114+
# q2 = main_search(q2, request.json)
112115

113116
return get_all_zh(
114117
info_role=g.current_user,
@@ -123,7 +126,7 @@ def get_zh(scope):
123126
def get_all_zh(info_role, query, limit, page, orderby=None, order="asc"):
124127
# try:
125128
# Pour obtenir le nombre de résultat de la requete sans le LIMIT
126-
nb_results_without_limit = query.count()
129+
nb_results_without_limit = DB.session.scalar(select(func.count()).select_from(query.subquery()))
127130
user = info_role
128131
user_cruved = get_user_cruved()
129132

@@ -151,7 +154,7 @@ def get_all_zh(info_role, query, limit, page, orderby=None, order="asc"):
151154

152155
# Order by id because there can be ambiguity in order_by(col) depending
153156
# on the column so add on order_by id makes it clearer
154-
data = query.order_by(TZH.id_zh).limit(limit).offset(page * limit).all()
157+
data = DB.session.scalars(query.order_by(TZH.id_zh).limit(limit).offset(page * limit)).all()
155158
is_ref_geo = check_ref_geo_schema()
156159

157160
featureCollection = []
@@ -336,8 +339,7 @@ def get_pbf():
336339
SELECT ST_AsGeobuf(q, 'geom') as pbf
337340
FROM (SELECT id_zh, geom from pr_zh.t_zh tz) AS q;
338341
"""
339-
query = DB.session.execute(sql)
340-
row = query.first()
342+
row = DB.session.execute(text(sql)).first()
341343
return Response(bytes(row["pbf"]) if row["pbf"] else bytes(), mimetype="application/protobuf")
342344

343345

@@ -364,8 +366,7 @@ def get_pbf_complete():
364366
'bassin_versant', tz.bassin_versant) as json_arrays
365367
FROM pr_zh.atlas_app tz) AS q;
366368
"""
367-
query = DB.session.execute(sql)
368-
row = query.first()
369+
row = DB.session.execute(text(sql)).first()
369370
return Response(bytes(row["pbf"]) if row["pbf"] else bytes(), mimetype="application/protobuf")
370371

371372

@@ -385,8 +386,7 @@ def get_json():
385386
) AS feature
386387
FROM (SELECT * FROM pr_zh.atlas_app tz) inputs) features;
387388
"""
388-
query = DB.session.execute(sql)
389-
row = query.first()
389+
row = DB.session.execute(text(sql)).first()
390390
return row["geojson"]
391391

392392

@@ -396,7 +396,7 @@ def get_json():
396396
def get_geometries():
397397
"""Get list of all zh geometries (contours)"""
398398
try:
399-
if not DB.session.query(TZH).all():
399+
if not DB.session.execute(select(TZH)).all():
400400
raise ZHApiError(
401401
message="no_geometry",
402402
details="Empty list of zh returned from get_zh_list db request",
@@ -406,7 +406,7 @@ def get_geometries():
406406
"geometry": zh.get_geofeature()["geometry"],
407407
"id_zh": zh.get_geofeature()["properties"]["id_zh"],
408408
}
409-
for zh in DB.session.query(TZH).all()
409+
for zh in DB.session.scalars(select(TZH)).all()
410410
]
411411
except Exception as e:
412412
if e.__class__.__name__ == "ZHApiError":
@@ -428,17 +428,14 @@ def get_ref_autocomplete():
428428
params = request.args
429429
search_title = params.get("search_title")
430430
# search_title = 'MCD'
431-
q = DB.session.query(
432-
TReferences,
433-
func.similarity(TReferences.title, search_title).label("idx_trgm"),
434-
)
431+
q = select(TReferences, func.similarity(TReferences.title, search_title).label("idx_trgm"))
435432

436433
search_title = search_title.replace(" ", "%")
437-
q = q.filter(TReferences.title.ilike("%" + search_title + "%")).order_by(desc("idx_trgm"))
434+
q = q.where(TReferences.title.ilike("%" + search_title + "%")).order_by(desc("idx_trgm"))
438435

439436
limit = request.args.get("limit", 20)
440437

441-
data = q.limit(limit).all()
438+
data = DB.session.execute(q.limit(limit)).all()
442439
if data:
443440
return [d[0].as_dict() for d in data]
444441
else:
@@ -462,17 +459,16 @@ def get_file_list(id_zh):
462459
"""get a list of the zh files contained in static repo"""
463460
try:
464461
# FIXME: to optimize... See relationships and lazy join with sqlalchemy
465-
zh_uuid = DB.session.query(TZH).filter(TZH.id_zh == id_zh).one().zh_uuid
466-
q_medias = (
467-
DB.session.query(TMedias, TNomenclatures.label_default)
468-
.filter(TMedias.unique_id_media == zh_uuid)
462+
zh_uuid = DB.session.scalar(select(TZH.zh_uuid).where(TZH.id_zh == id_zh))
463+
q_medias = DB.session.execute(
464+
select(TMedias, TNomenclatures.label_default)
469465
.join(
470466
TNomenclatures,
471467
TNomenclatures.id_nomenclature == TMedias.id_nomenclature_media_type,
472468
)
469+
.where(TMedias.unique_id_media == zh_uuid)
473470
.order_by(TMedias.meta_update_date.desc())
474-
.all()
475-
)
471+
).all()
476472
res_media, image_medias = [], []
477473
for media, media_type in q_medias:
478474
res_media.append(media)
@@ -528,9 +524,12 @@ def post_main_pict(id_zh, id_media):
528524
"""post main picture id in tzh"""
529525
try:
530526
# FIXME: after insert+after update on t_zh => update_date=dt.now()
531-
DB.session.query(TZH).filter(TZH.id_zh == id_zh).update(
532-
{TZH.main_pict_id: id_media, TZH.update_date: dt.now()}
527+
stmt = (
528+
update(TZH)
529+
.where(TZH.id_zh == id_zh)
530+
.values(main_pict_id=id_media, update_date=dt.now())
533531
)
532+
DB.session.execute(stmt)
534533
DB.session.commit()
535534
return ("", 204)
536535
except Exception as e:
@@ -553,18 +552,16 @@ def post_main_pict(id_zh, id_media):
553552
@blueprint.route("<int:id_zh>/photos", methods=["GET"])
554553
@json_resp
555554
def get_all_photos(id_zh: int):
556-
q_medias = (
557-
DB.session.query(TZH.main_pict_id, TMedias.id_media, TMedias.media_path)
555+
q_medias = DB.session.execute(
556+
select(TZH.main_pict_id, TMedias.id_media, TMedias.media_path)
558557
.join(TZH, TZH.zh_uuid == TMedias.unique_id_media)
559558
.join(
560559
TNomenclatures,
561560
TNomenclatures.id_nomenclature == TMedias.id_nomenclature_media_type,
562561
)
563562
.order_by(TMedias.meta_update_date.desc())
564-
.filter(TNomenclatures.label_default == "Photo")
565-
.filter(TZH.id_zh == id_zh)
566-
.all()
567-
)
563+
.where(TNomenclatures.label_default == "Photo", TZH.id_zh == id_zh)
564+
).all()
568565
api_uri = urljoin(
569566
f"{config['API_ENDPOINT']}/",
570567
f"{blueprint.config['MODULE_CODE'].lower()}/{blueprint.config['file_path']}/",
@@ -595,9 +592,7 @@ def get_tab_data(id_tab):
595592
)
596593

597594
# select active geo refs in config
598-
active_geo_refs = [
599-
ref for ref in blueprint.config["ref_geo_referentiels"] if ref["active"]
600-
]
595+
active_geo_refs = [ref for ref in blueprint.config["ref_geo_referentiels"] if ref["active"]]
601596
intersection = None
602597
# Check on geometry that should always exist (PATCH or POST)
603598
if len(form_data["geom"]["geometry"]["coordinates"]) == 0:
@@ -735,7 +730,7 @@ def patch_file(id_media):
735730
ALLOWED_EXTENSIONS = blueprint.config["allowed_extensions"]
736731
MAX_PDF_SIZE = blueprint.config["max_pdf_size"]
737732
MAX_JPG_SIZE = blueprint.config["max_jpg_size"]
738-
FILE_PATH = blueprint.config["file_path"]
733+
FILE_PATH = Path(BACKEND_DIR, config["MEDIA_FOLDER"], "attachments")
739734
MODULE_NAME = blueprint.config["MODULE_CODE"].lower()
740735

741736
upload_resp = upload_process(
@@ -750,13 +745,11 @@ def patch_file(id_media):
750745

751746
DB.session.commit()
752747

753-
return jsonify(
754-
{
755-
"media_path": upload_resp["media_path"],
756-
"secured_file_name": upload_resp["secured_file_name"],
757-
"id_media": upload_resp["id_media"],
758-
}
759-
)
748+
return {
749+
"media_path": upload_resp["media_path"],
750+
"secured_file_name": upload_resp["secured_file_name"],
751+
"id_media": upload_resp["id_media"],
752+
}
760753

761754

762755
@blueprint.route("/<int:id_zh>", methods=["DELETE"])
@@ -771,18 +764,18 @@ def deleteOneZh(id_zh):
771764
zhRepository = ZhRepository(TZH)
772765

773766
# delete references
774-
DB.session.query(CorZhRef).filter(CorZhRef.id_zh == id_zh).delete()
767+
DB.session.execute(delete(CorZhRef).where(CorZhRef.id_zh == id_zh))
775768

776769
# delete criteres delim
777-
id_lim_list = DB.session.query(TZH).filter(TZH.id_zh == id_zh).one().id_lim_list
778-
DB.session.query(CorLimList).filter(CorLimList.id_lim_list == id_lim_list).delete()
770+
id_lim_list = DB.session.execute(select(TZH.id_lim_list).where(TZH.id_zh == id_zh)).scalar_one()
771+
DB.session.execute(delete(CorLimList).where(CorLimList.id_lim_list == id_lim_list))
779772

780773
# delete cor_zh_area
781-
DB.session.query(CorZhArea).filter(CorZhArea.id_zh == id_zh).delete()
774+
DB.session.execute(delete(CorZhArea).where(CorZhArea.id_zh == id_zh))
782775

783776
# delete files in TMedias and repos
784-
zh_uuid = DB.session.query(TZH).filter(TZH.id_zh == id_zh).one().zh_uuid
785-
q_medias = DB.session.query(TMedias).filter(TMedias.unique_id_media == zh_uuid).all()
777+
zh_uuid = DB.session.execute(select(TZH.zh_uuid).where(TZH.id_zh == id_zh)).scalar_one()
778+
q_medias = DB.session.scalars(select(TMedias).where(TMedias.unique_id_media == zh_uuid)).all()
786779
for media in q_medias:
787780
delete_file(media.id_media)
788781

@@ -807,18 +800,21 @@ def write_csv(id_zh):
807800
names = []
808801
FILE_PATH = blueprint.config["file_path"]
809802
MODULE_NAME = blueprint.config["MODULE_CODE"].lower()
810-
zh_code = DB.session.query(TZH).filter(TZH.id_zh == id_zh).one().code
803+
zh_code = DB.session.scalar(select(TZH.code).where(TZH.id_zh == id_zh))
811804
# author name
812-
user = DB.session.query(User).filter(User.id_role == g.current_user.id_role).one()
805+
user = DB.session.execute(
806+
select(User).where(User.id_role == g.current_user.id_role)
807+
).scalar_one()
813808
author = user.prenom_role + " " + user.nom_role
814809
for i in ["vertebrates_view_name", "invertebrates_view_name", "flora_view_name"]:
815810
query = GenericQuery(
816811
DB=DB,
817812
tableName=blueprint.config[i]["table_name"],
818813
schemaName=blueprint.config[i]["schema_name"],
819814
filters={"id_zh": id_zh, "orderby": "id_zh"},
820-
limit=-1,
815+
# TODO: limit=-1 when version 0.4.2 of Utils-Flask-SQLAlchemy will be released
821816
)
817+
822818
results = query.return_query().get("items", [])
823819
current_date = dt.now()
824820
if results:
@@ -868,8 +864,10 @@ def write_csv(id_zh):
868864
DB.session.flush()
869865

870866
# update TMedias.media_path with media_filename
871-
DB.session.query(TMedias).filter(TMedias.id_media == id_media).update(
872-
{"media_path": str(media_path)}
867+
DB.session.execute(
868+
update(TMedias)
869+
.where(TMedias.id_media == id_media)
870+
.values(media_path=str(media_path))
873871
)
874872

875873
DB.session.commit()
@@ -928,41 +926,43 @@ def download(id_zh: int):
928926
@json_resp
929927
def departments():
930928
query = (
931-
DB.session.query(LAreas)
932-
.with_entities(LAreas.area_name, LAreas.area_code, LAreas.id_type, BibAreasTypes.type_code)
929+
select(LAreas)
930+
.with_only_columns(
931+
LAreas.area_name, LAreas.area_code, LAreas.id_type, BibAreasTypes.type_code
932+
)
933933
.join(BibAreasTypes, LAreas.id_type == BibAreasTypes.id_type)
934-
.filter(BibAreasTypes.type_code == "DEP")
935-
.filter(LAreas.enable)
934+
.where(BibAreasTypes.type_code == "DEP")
935+
.where(LAreas.enable)
936936
.order_by(LAreas.area_code)
937937
)
938-
resp = query.all()
938+
resp = DB.session.execute(query).all()
939939
return [{"code": r.area_code, "name": r.area_name} for r in resp]
940940

941941

942942
@blueprint.route("/communes", methods=["POST"])
943943
@json_resp
944944
def get_area_from_department() -> dict:
945+
# route utilisée ?
945946
code = request.json.get("code")
946947
if code:
947948
query = (
948-
DB.session.query(LiMunicipalities)
949-
.with_entities(LiMunicipalities.id_area, LAreas.area_name, LAreas.area_code)
949+
select(LiMunicipalities)
950+
.with_only_columns(LiMunicipalities.id_area, LAreas.area_name, LAreas.area_code)
950951
.join(LAreas, LiMunicipalities.id_area == LAreas.id_area)
951-
.filter(LiMunicipalities.insee_com.like("{}%".format(code)))
952-
.filter(LAreas.enable)
952+
.where(LiMunicipalities.insee_com.like("{}%".format(code)))
953+
.where(LAreas.enable)
954+
.order_by(LAreas.area_code)
953955
)
954-
query = query.order_by(LAreas.area_code)
955-
resp = query.all()
956+
resp = DB.session.execute(query).all()
956957
return [{"code": r.area_code, "name": r.area_name} for r in resp]
957-
958958
return []
959959

960960

961961
@blueprint.route("/bassins", methods=["GET"])
962962
@json_resp
963963
def bassins():
964-
query = DB.session.query(TRiverBasin).with_entities(TRiverBasin.id_rb, TRiverBasin.name)
965-
resp = query.order_by(TRiverBasin.name).all()
964+
query = select(TRiverBasin.id_rb, TRiverBasin.name).order_by(TRiverBasin.name)
965+
resp = DB.session.execute(query).all()
966966
return [{"code": r.id_rb, "name": r.name} for r in resp]
967967

968968

@@ -972,19 +972,19 @@ def get_hydro_zones_from_bassin() -> dict:
972972
code = request.json.get("code")
973973
if code:
974974
query = (
975-
DB.session.query(THydroArea)
976-
.with_entities(THydroArea.id_hydro, THydroArea.name, TRiverBasin.id_rb)
977-
.filter(TRiverBasin.id_rb == code)
975+
select(THydroArea.id_hydro, THydroArea.name, TRiverBasin.id_rb)
976+
.where(TRiverBasin.id_rb == code)
978977
.join(
979978
TRiverBasin,
980979
func.ST_Contains(
981980
func.ST_SetSRID(TRiverBasin.geom, 4326),
982981
func.ST_SetSRID(THydroArea.geom, 4326),
983982
),
984983
)
984+
.order_by(THydroArea.name)
985985
)
986986

987-
resp = query.order_by(THydroArea.name).all()
987+
resp = DB.session.execute(query).all()
988988
return [{"code": r.id_hydro, "name": r.name} for r in resp]
989989

990990
return []

backend/gn_module_zh/conf_schema_toml.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@ class MapListConfig(Schema):
103103

104104
vertebrates_view_name = {
105105
"schema_name": "pr_zh",
106-
"table_name": "vertebrates",
106+
"table_name": "vm_vertebrates",
107107
"category": "vertebrates",
108108
}
109109

110110
invertebrates_view_name = {
111111
"schema_name": "pr_zh",
112-
"table_name": "invertebrates",
112+
"table_name": "vm_invertebrates",
113113
"category": "invertebrates",
114114
}
115115

116-
flora_view_name = {"schema_name": "pr_zh", "table_name": "flora", "category": "flora"}
116+
flora_view_name = {"schema_name": "pr_zh", "table_name": "vm_flora", "category": "flora"}
117117

118118
# Name of the source of species data (tab5)
119119
species_source_name = "GeoNature"
@@ -178,3 +178,4 @@ class GnModuleSchemaConf(Schema):
178178
pdf_small_layer_number = fields.Integer(load_default=pdf_small_layer_number)
179179
pdf_last_page_img = fields.String(load_default=pdf_last_page_img)
180180
pdf_title = fields.String(load_default=pdf_title)
181+
TAXON_VM_CRONTAB = fields.String(load_default="0 0,12 * * *")

0 commit comments

Comments
 (0)