From 3f90d47fd4499e37afdbee5a36d394e9a79f4b53 Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Fri, 12 Apr 2024 18:00:50 +0200 Subject: [PATCH 1/8] feat: improve the display time of meshes on the species map --- atlas/atlasAPI.py | 12 ++--- atlas/modeles/entities/tMaillesTerritoire.py | 22 +++++++++ atlas/modeles/entities/vmObservations.py | 9 ++-- .../vmObservationsMaillesRepository.py | 29 +++++++----- data/atlas/12.atlas.t_mailles_territoire.sql | 27 ++++++----- .../13.atlas.vm_observations_mailles.sql | 30 ++++++++----- data/update/update_1.6.1to1.6.2.sql | 45 +++++++++++++++++++ 7 files changed, 131 insertions(+), 43 deletions(-) create mode 100644 atlas/modeles/entities/tMaillesTerritoire.py create mode 100644 data/update/update_1.6.1to1.6.2.sql diff --git a/atlas/atlasAPI.py b/atlas/atlasAPI.py index 9af3beacb..de661edce 100644 --- a/atlas/atlasAPI.py +++ b/atlas/atlasAPI.py @@ -56,7 +56,7 @@ def getObservationsMailleAndPointAPI(cd_ref): @api.route("/observationsMaille/", methods=["GET"]) -def getObservationsMailleAPI(cd_ref, year_min=None, year_max=None): +def getObservationsMailleAPI(cd_ref): """ Retourne les observations d'un taxon par maille (et le nombre d'observation par maille) @@ -94,17 +94,17 @@ def getObservationsGenericApi(cd_ref: int): [type]: [description] """ session = db.session - observations = ( - vmObservationsMaillesRepository.getObservationsMaillesChilds( + if current_app.config["AFFICHAGE_MAILLE"]: + observations = vmObservationsMaillesRepository.getObservationsMaillesChilds( session, cd_ref, year_min=request.args.get("year_min"), year_max=request.args.get("year_max"), ) - if current_app.config["AFFICHAGE_MAILLE"] - else vmObservationsRepository.searchObservationsChilds(session, cd_ref) - ) + else: + observations = vmObservationsRepository.searchObservationsChilds(session, cd_ref) session.close() + return jsonify(observations) diff --git a/atlas/modeles/entities/tMaillesTerritoire.py b/atlas/modeles/entities/tMaillesTerritoire.py new file mode 100644 index 000000000..8a8a7c3bd --- /dev/null +++ b/atlas/modeles/entities/tMaillesTerritoire.py @@ -0,0 +1,22 @@ +# coding: utf-8 +from geoalchemy2.types import Geometry +from sqlalchemy import Column, Integer, MetaData, Table, Text +from sqlalchemy.ext.declarative import declarative_base + +from atlas.utils import engine + +metadata = MetaData() +Base = declarative_base() + + +class TMaillesTerritoire(Base): + __table__ = Table( + "t_mailles_territoire", + metadata, + Column("id_maille", Integer, primary_key=True, unique=True), + Column("the_geom", Geometry()), + Column("geojson_maille", Text), + schema="atlas", + autoload=True, + autoload_with=engine, + ) diff --git a/atlas/modeles/entities/vmObservations.py b/atlas/modeles/entities/vmObservations.py index 782664297..141fd7514 100644 --- a/atlas/modeles/entities/vmObservations.py +++ b/atlas/modeles/entities/vmObservations.py @@ -36,11 +36,10 @@ class VmObservationsMailles(Base): __table__ = Table( "vm_observations_mailles", metadata, - Column("id_observation", Integer, primary_key=True, unique=True), - Column("id_maille", Integer), - Column("the_geom", Geometry), - Column("geojson_maille", Text), - Column("annee", String(1000)), + Column("cd_ref", Integer, primary_key=True, index=True), + Column("annee", String(1000), primary_key=True, index=True), + Column("id_maille", Integer, primary_key=True, index=True), + Column("nbr", Integer), schema="atlas", autoload=True, autoload_with=db.engine, diff --git a/atlas/modeles/repositories/vmObservationsMaillesRepository.py b/atlas/modeles/repositories/vmObservationsMaillesRepository.py index 0a37ae047..5a3180fb1 100644 --- a/atlas/modeles/repositories/vmObservationsMaillesRepository.py +++ b/atlas/modeles/repositories/vmObservationsMaillesRepository.py @@ -1,9 +1,10 @@ import json from geojson import Feature, FeatureCollection -from sqlalchemy.sql import text, func, or_ +from sqlalchemy.sql import text, func, any_ from atlas.modeles.entities.vmObservations import VmObservationsMailles +from atlas.modeles.entities.tMaillesTerritoire import TMaillesTerritoire from atlas.modeles.utils import deleteAccent, findPath @@ -12,17 +13,25 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): Retourne les mailles et le nombre d'observation par maille pour un taxon et ses enfants sous forme d'un geojson """ - subquery = session.query(func.atlas.find_all_taxons_childs(cd_ref)) + query = session.query(func.atlas.find_all_taxons_childs(cd_ref)) + taxons_ids = query.all() + taxons_ids.append(cd_ref) + query = ( session.query( - func.count(VmObservationsMailles.id_observation).label("nb_obs"), - func.max(VmObservationsMailles.annee).label("last_observation"), VmObservationsMailles.id_maille, - VmObservationsMailles.geojson_maille, + TMaillesTerritoire.geojson_maille, + func.max(VmObservationsMailles.annee).label("last_obs_year"), + func.count(VmObservationsMailles.nbr).label("obs_nbr"), + ) + .join( + TMaillesTerritoire, + TMaillesTerritoire.id_maille == VmObservationsMailles.id_maille, ) - .group_by(VmObservationsMailles.id_maille, VmObservationsMailles.geojson_maille) - .filter( - or_(VmObservationsMailles.cd_ref.in_(subquery), VmObservationsMailles.cd_ref == cd_ref) + .filter(VmObservationsMailles.cd_ref == any_(taxons_ids)) + .group_by( + VmObservationsMailles.id_maille, + TMaillesTerritoire.geojson_maille, ) ) if year_min and year_max: @@ -35,8 +44,8 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): geometry=json.loads(o.geojson_maille), properties={ "id_maille": o.id_maille, - "nb_observations": o.nb_obs, - "last_observation": o.last_observation, + "nb_observations": o.obs_nbr, + "last_observation": o.last_obs_year, }, ) for o in query.all() diff --git a/data/atlas/12.atlas.t_mailles_territoire.sql b/data/atlas/12.atlas.t_mailles_territoire.sql index d19ee8613..9f6c07064 100644 --- a/data/atlas/12.atlas.t_mailles_territoire.sql +++ b/data/atlas/12.atlas.t_mailles_territoire.sql @@ -1,14 +1,19 @@ DROP TABLE IF EXISTS atlas.t_mailles_territoire; --- MV for having only meshs of the territory -CREATE TABLE atlas.t_mailles_territoire -AS SELECT -st_transform(c.geom, 4326) AS the_geom, -st_asgeojson(st_transform(c.geom, 4326)) AS geojson_maille, -c.id_area AS id_maille -FROM ref_geo.l_areas c -JOIN ref_geo.bib_areas_types t ON t.id_type = c.id_type -JOIN atlas.t_layer_territoire mt ON ST_intersects(c.geom,st_transform(mt.the_geom, find_srid('ref_geo', 'l_areas', 'geom'))) -WHERE c.enable = true AND t.type_code = :type_maille; +CREATE TABLE atlas.t_mailles_territoire AS + SELECT + st_transform(a.geom, 4326) AS the_geom, + st_asgeojson(st_transform(a.geom, 4326)) AS geojson_maille, + a.id_area AS id_maille + FROM ref_geo.l_areas AS a + JOIN ref_geo.bib_areas_types AS t + ON t.id_type = a.id_type + JOIN atlas.t_layer_territoire AS l + ON ST_intersects(a.geom, st_transform(l.the_geom, find_srid('ref_geo', 'l_areas', 'geom'))) + WHERE a.enable = true + AND t.type_code = :type_maille ; -CREATE UNIQUE INDEX t_mailles_territoire_id_maille_idx ON atlas.t_mailles_territoire USING btree (id_maille); \ No newline at end of file +CREATE UNIQUE INDEX ON atlas.t_mailles_territoire + USING btree (id_maille); +CREATE INDEX ON atlas.t_mailles_territoire + USING spgist (the_geom); diff --git a/data/atlas/13.atlas.vm_observations_mailles.sql b/data/atlas/13.atlas.vm_observations_mailles.sql index 659744fb4..557bfa75e 100644 --- a/data/atlas/13.atlas.vm_observations_mailles.sql +++ b/data/atlas/13.atlas.vm_observations_mailles.sql @@ -1,13 +1,21 @@ -CREATE MATERIALIZED VIEW atlas.vm_observations_mailles -AS SELECT obs.cd_ref, -obs.id_observation, -m.id_maille, -m.geojson_maille, -date_part('year', dateobs) as annee -FROM atlas.vm_observations obs -JOIN atlas.t_mailles_territoire m ON st_intersects(obs.the_geom_point, m.the_geom) +CREATE MATERIALIZED VIEW atlas.vm_observations_mailles AS + SELECT + o.cd_ref, + date_part('year', o.dateobs) AS annee, + m.id_maille, + COUNT(o.id_observation) AS nbr + FROM atlas.vm_observations AS o + JOIN atlas.t_mailles_territoire AS m + ON (o.the_geom_point && m.the_geom) + GROUP BY o.cd_ref, date_part('year', o.dateobs), m.id_maille + ORDER BY o.cd_ref, annee WITH DATA; -create unique index on atlas.vm_observations_mailles (id_observation); -create index on atlas.vm_observations_mailles (id_maille); -create index on atlas.vm_observations_mailles (cd_ref); \ No newline at end of file +CREATE UNIQUE INDEX ON atlas.vm_observations_mailles + USING btree (cd_ref, annee, id_maille); + +CREATE INDEX ON atlas.vm_observations_mailles + USING btree (annee); + +CREATE INDEX ON atlas.vm_observations_mailles + USING btree (id_maille, cd_ref); diff --git a/data/update/update_1.6.1to1.6.2.sql b/data/update/update_1.6.1to1.6.2.sql new file mode 100644 index 000000000..8841c9526 --- /dev/null +++ b/data/update/update_1.6.1to1.6.2.sql @@ -0,0 +1,45 @@ +DROP MATERIALIZED VIEW IF EXISTS atlas.vm_observations_mailles; +DROP TABLE IF EXISTS atlas.t_mailles_territoire; + + +CREATE TABLE atlas.t_mailles_territoire AS + SELECT + st_transform(a.geom, 4326) AS the_geom, + st_asgeojson(st_transform(a.geom, 4326)) AS geojson_maille, + a.id_area AS id_maille + FROM ref_geo.l_areas AS a + JOIN ref_geo.bib_areas_types AS t + ON t.id_type = a.id_type + JOIN atlas.t_layer_territoire AS l + ON ST_intersects(a.geom, st_transform(l.the_geom, find_srid('ref_geo', 'l_areas', 'geom'))) + WHERE a.enable = true + AND t.type_code = :type_maille ; + +CREATE UNIQUE INDEX ON atlas.t_mailles_territoire + USING btree (id_maille); + +CREATE INDEX ON atlas.t_mailles_territoire + USING spgist (the_geom); + + +CREATE MATERIALIZED VIEW atlas.vm_observations_mailles AS + SELECT + o.cd_ref, + date_part('year', o.dateobs) AS annee, + m.id_maille, + COUNT(o.id_observation) AS nbr + FROM atlas.vm_observations AS o + JOIN atlas.t_mailles_territoire AS m + ON (o.the_geom_point && m.the_geom) + GROUP BY o.cd_ref, date_part('year', o.dateobs), m.id_maille + ORDER BY o.cd_ref, annee +WITH DATA; + +CREATE UNIQUE INDEX ON atlas.vm_observations_mailles + USING btree (cd_ref, annee, id_maille); + +CREATE INDEX ON atlas.vm_observations_mailles + USING btree (annee); + +CREATE INDEX ON atlas.vm_observations_mailles + USING btree (id_maille, cd_ref); From 36d6f1ecd0a60ae49a44d43aa49576a452e6a30e Mon Sep 17 00:00:00 2001 From: Geoffrey Brun <68049696+geobrun@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:23:04 +0200 Subject: [PATCH 2/8] Update sideBar.html --- atlas/templates/core/sideBar.html | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/atlas/templates/core/sideBar.html b/atlas/templates/core/sideBar.html index d9c9b4a8e..f99cd2a23 100644 --- a/atlas/templates/core/sideBar.html +++ b/atlas/templates/core/sideBar.html @@ -7,12 +7,24 @@ {% if 'url' in page_values %} - + {% else %} - + {% endif %} {% endfor %} From fad1301c5d28b35dc14b2fc21611ef717c3095da Mon Sep 17 00:00:00 2001 From: Geoffrey Brun <68049696+geobrun@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:26:30 +0200 Subject: [PATCH 3/8] Update sideBar.html --- atlas/templates/core/sideBar.html | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/atlas/templates/core/sideBar.html b/atlas/templates/core/sideBar.html index f99cd2a23..09285c98e 100644 --- a/atlas/templates/core/sideBar.html +++ b/atlas/templates/core/sideBar.html @@ -5,26 +5,24 @@ {% for page_key, page_values in configuration.STATIC_PAGES.items()|sort(attribute='1.order') %} {% if 'url' in page_values %} - + + {% if 'customized_picto' in page_values %} + + {% else %} + + {% endif %} + {% else %} - + + {% if 'customized_picto' in page_values %} + + {% else %} + + {% endif %} + {% endif %} {% endfor %} From 9b856ecbf0d8d1b7191952635b04ded0c364f2eb Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Tue, 16 Apr 2024 15:01:21 +0200 Subject: [PATCH 4/8] fix: use sum instead of count with new observations mailles MV --- atlas/modeles/repositories/vmObservationsMaillesRepository.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atlas/modeles/repositories/vmObservationsMaillesRepository.py b/atlas/modeles/repositories/vmObservationsMaillesRepository.py index 5a3180fb1..46e53e1c7 100644 --- a/atlas/modeles/repositories/vmObservationsMaillesRepository.py +++ b/atlas/modeles/repositories/vmObservationsMaillesRepository.py @@ -22,7 +22,7 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): VmObservationsMailles.id_maille, TMaillesTerritoire.geojson_maille, func.max(VmObservationsMailles.annee).label("last_obs_year"), - func.count(VmObservationsMailles.nbr).label("obs_nbr"), + func.sum(VmObservationsMailles.nbr).label("obs_nbr"), ) .join( TMaillesTerritoire, @@ -44,7 +44,7 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): geometry=json.loads(o.geojson_maille), properties={ "id_maille": o.id_maille, - "nb_observations": o.obs_nbr, + "nb_observations": int(o.obs_nbr), "last_observation": o.last_obs_year, }, ) From c560a91ec04e60273402b8bf3fb5f031b8cdf1f0 Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Tue, 16 Apr 2024 16:12:36 +0200 Subject: [PATCH 5/8] fix: get integer from find_all_taxons_childs() --- atlas/modeles/repositories/vmObservationsMaillesRepository.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atlas/modeles/repositories/vmObservationsMaillesRepository.py b/atlas/modeles/repositories/vmObservationsMaillesRepository.py index 46e53e1c7..d2ec6fdc6 100644 --- a/atlas/modeles/repositories/vmObservationsMaillesRepository.py +++ b/atlas/modeles/repositories/vmObservationsMaillesRepository.py @@ -13,8 +13,8 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): Retourne les mailles et le nombre d'observation par maille pour un taxon et ses enfants sous forme d'un geojson """ - query = session.query(func.atlas.find_all_taxons_childs(cd_ref)) - taxons_ids = query.all() + query = func.atlas.find_all_taxons_childs(cd_ref) + taxons_ids = session.scalars(query).all() taxons_ids.append(cd_ref) query = ( From 5e1f8b3f3058c7932229cc177bf0f3210471a8bb Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Tue, 7 May 2024 11:06:17 +0200 Subject: [PATCH 6/8] fix(modeles): use right db engine import --- atlas/modeles/entities/tMaillesTerritoire.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atlas/modeles/entities/tMaillesTerritoire.py b/atlas/modeles/entities/tMaillesTerritoire.py index 8a8a7c3bd..0e8a83513 100644 --- a/atlas/modeles/entities/tMaillesTerritoire.py +++ b/atlas/modeles/entities/tMaillesTerritoire.py @@ -3,7 +3,7 @@ from sqlalchemy import Column, Integer, MetaData, Table, Text from sqlalchemy.ext.declarative import declarative_base -from atlas.utils import engine +from atlas.env import db metadata = MetaData() Base = declarative_base() @@ -18,5 +18,5 @@ class TMaillesTerritoire(Base): Column("geojson_maille", Text), schema="atlas", autoload=True, - autoload_with=engine, + autoload_with=db.engine, ) From 39782633f370a5c4ced52c905946683316886cf7 Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Tue, 7 May 2024 11:08:37 +0200 Subject: [PATCH 7/8] fix(requirements): use greenlet v1.1.3 for Debian 12 Fix #494, Resolve #501. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bcf9dca3f..ec1fe5e39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -36,7 +36,7 @@ geoalchemy2==0.9.4 # via -r requirements.in geojson==2.5.0 # via -r requirements.in -greenlet==1.1.2 +greenlet==1.1.3 # via sqlalchemy gunicorn==20.1.0 # via -r requirements.in From a8d40c4fb0cc3611a79b9cebde1ed07dfa63ae1b Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Tue, 7 May 2024 17:14:43 +0200 Subject: [PATCH 8/8] feat(identityCard): improve subtaxa modal Refactor SQL queries and Python source code. Fix map bounds error for municipality view for sensitive taxa with no data. Fix HTML tags and Jinja conditions. Add changelog entry. Improve subtaxa table responsiveness. Resolve #558. --- .../repositories/vmTaxrefRepository.py | 52 ++++++++------ atlas/static/mapAreas.js | 5 -- atlas/static/mapGenerator.js | 4 +- .../templates/speciesSheet/identityCard.html | 72 ++++++++++--------- docs/changelog.rst | 8 +++ 5 files changed, 77 insertions(+), 64 deletions(-) diff --git a/atlas/modeles/repositories/vmTaxrefRepository.py b/atlas/modeles/repositories/vmTaxrefRepository.py index a5e5b51d0..8eab16957 100644 --- a/atlas/modeles/repositories/vmTaxrefRepository.py +++ b/atlas/modeles/repositories/vmTaxrefRepository.py @@ -11,29 +11,34 @@ def searchEspece(connection, cd_ref): """ recherche l espece corespondant au cd_nom et tout ces fils """ - sql = """ + query = """ WITH limit_obs AS ( SELECT - :thiscdref AS cd_ref, min(yearmin) AS yearmin, - max(yearmax) AS yearmax, SUM(nb_obs) AS nb_obs + :cdRef AS cd_ref, + MIN(yearmin) AS yearmin, + MAX(yearmax) AS yearmax, + SUM(nb_obs) AS nb_obs FROM atlas.vm_taxons - WHERE - cd_ref IN (SELECT * FROM atlas.find_all_taxons_childs(:thiscdref)) - OR cd_ref = :thiscdref + WHERE cd_ref IN (SELECT * FROM atlas.find_all_taxons_childs(:cdRef)) + OR cd_ref = :cdRef ) SELECT taxref.*, - l.cd_ref, l.yearmin, l.yearmax, COALESCE(l.nb_obs, 0) AS nb_obs, - t2.patrimonial, t2.protection_stricte - FROM atlas.vm_taxref taxref - JOIN limit_obs l - ON l.cd_ref = taxref.cd_nom - LEFT JOIN atlas.vm_taxons t2 - ON t2.cd_ref = taxref.cd_ref - WHERE taxref.cd_nom = :thiscdref + l.cd_ref, + l.yearmin, + l.yearmax, + COALESCE(l.nb_obs, 0) AS nb_obs, + t2.patrimonial, + t2.protection_stricte + FROM atlas.vm_taxref AS taxref + JOIN limit_obs AS l + ON l.cd_ref = taxref.cd_nom + LEFT JOIN atlas.vm_taxons AS t2 + ON t2.cd_ref = taxref.cd_ref + WHERE taxref.cd_nom = :cdRef """ - req = connection.execute(text(sql), thiscdref=cd_ref) + results = connection.execute(text(query), cdRef=cd_ref) taxonSearch = dict() - for r in req: + for r in results: nom_vern = None if r.nom_vern: nom_vern = ( @@ -54,7 +59,7 @@ def searchEspece(connection, cd_ref): "protection": r.protection_stricte, } - sql = """ + query = """ SELECT tax.lb_nom, tax.nom_vern, @@ -64,16 +69,17 @@ def searchEspece(connection, cd_ref): tax.patrimonial, tax.protection_stricte, tax.nb_obs - FROM atlas.vm_taxons tax - JOIN atlas.bib_taxref_rangs br - ON br.id_rang = tax.id_rang + FROM atlas.vm_taxons AS tax + JOIN atlas.bib_taxref_rangs AS br + ON br.id_rang = tax.id_rang WHERE tax.cd_ref IN ( - SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) + SELECT * FROM atlas.find_all_taxons_childs(:cdRef) ) + ORDER BY tax.lb_nom ASC, tax.nb_obs DESC """ - req = connection.execute(text(sql), thiscdref=cd_ref) + results = connection.execute(text(query), cdRef=cd_ref) listTaxonsChild = list() - for r in req: + for r in results: temp = { "lb_nom": r.lb_nom, "nom_vern": r.nom_vern, diff --git a/atlas/static/mapAreas.js b/atlas/static/mapAreas.js index 66e00b73f..1baeb8a15 100644 --- a/atlas/static/mapAreas.js +++ b/atlas/static/mapAreas.js @@ -148,11 +148,6 @@ function displayObsTaxonMaille(areaCode, cd_ref) { dataType: "json", beforeSend: function () { $("#loaderSpinner").show(); - // $("#loadingGif").show(); - // $("#loadingGif").attr( - // "src", - // configuration.URL_APPLICATION + "/static/images/loading.svg" - // ); } }).done(function (observations) { $("#loaderSpinner").hide(); diff --git a/atlas/static/mapGenerator.js b/atlas/static/mapGenerator.js index 58c5892cb..e26446eb6 100644 --- a/atlas/static/mapGenerator.js +++ b/atlas/static/mapGenerator.js @@ -340,7 +340,9 @@ function displayGridLayerArea(observations) { style: styleMaille, }); currentLayer.addTo(map); - map.fitBounds(currentLayer.getBounds()); + if (currentLayer.getBounds().isValid()) { + map.fitBounds(currentLayer.getBounds()); + } // ajout de la légende generateLegendMaille(); diff --git a/atlas/templates/speciesSheet/identityCard.html b/atlas/templates/speciesSheet/identityCard.html index 9d7c4d273..f54a82bc8 100644 --- a/atlas/templates/speciesSheet/identityCard.html +++ b/atlas/templates/speciesSheet/identityCard.html @@ -109,17 +109,19 @@

{{ taxon.taxonSearch.nom_complet_html|safe }}