Leaflet应用中JQuery+Flask过滤GeoJSON图层失效问题求助
Leaflet复选框过滤GeoJSON无响应问题解决
问题描述
在Leaflet中使用复选框过滤GeoJSON图层,图层可正常显示,但点击复选框后无任何反应。Flask服务器显示请求已被接收,数据来自PostgreSQL,需修改Python代码实现地图显示过滤后的信息。
相关代码
JS代码
function refreshroutesfermees(whr) { if (whr) { var objData = {tbl:'routes_fermees_adn', flds:"id, cpx_numero, cpx_gestio, fermeture, dep", where:whr}; } else { var objData = {tbl:'routes_fermees_adn', flds:"id, cpx_numero, cpx_gestio, fermeture, dep"}; } $.ajax({ url: '/routes_fermees', ///retrieve my data from app.py data: objData, type: 'POST', success: function (response) { if (response=="ERROR"){ alert (response); } else { arProjectIDs=[]; if (lyrroutesfermees) { ctlLayers.removeLayer(lyrroutesfermees); lyrroutesfermees.remove(); } lyrroutesfermees = L.geoJSON(response, {style:styleroutesfermees, onEachFeature:processroutesfermees}); ctlLayers.addOverlay(lyrroutesfermees, "routes fermées"); arProjectIDs.sort(function(a,b){return a-b}); } }, error: function (xhr, status, error) { alert("ERROR: " + error); } }); }
HTML复选框代码
$("#btnFilterroutesfermees").click(function(){ var arTypes=[]; var cntChecks=0; $("input[name=fltferme]").each(function(){ if (this.checked) { if(this.value=='ferm 38'){ arTypes.push("'38'"); cntChecks++; } if(this.value=='ferm 73'){ arTypes.push("'73'"); cntChecks++; } if(this.value=='ferm 74'){ arTypes.push("'74'"); cntChecks++; } } }); // alert(cntChecks); if (cntChecks==0) { refreshroutesfermees("1=2"); } else if (cntChecks==3){ ////le nombre de checkbox refreshroutesfermees(); } else { // alert("type IN ("+arTypes.toString()+")"); refreshroutesfermees("dep IN ("+arTypes.toString()+")"); } });
app.py原代码
@app.route('/routes_fermees', methods=["POST", "GET"]) def routes_fermees(): cur = con.cursor() cur.execute(""" select json_build_object( 'type', 'FeatureCollection', 'features', json_agg(ST_AsGeoJSON(routes_fermees_adn.*)::json) ) as geojson from routes_fermees_adn """) return cur.fetchone()[0]
Flask生成的请求链接
GET /routes_fermees?tbl=routes_fermees_adn&flds=id%2C%20cpx_numero%2C%20cpx_gestio%2C%20fermeture%2C%20dep
问题原因
原app.py代码未处理前端传递的where过滤参数,无论前端发送什么过滤条件,后端始终返回全量数据,导致复选框点击后地图无变化。
修改方案
修改app.py代码,接收前端过滤条件并动态构造SQL查询,同时处理空结果和异常:
from flask import request, jsonify @app.route('/routes_fermees', methods=["POST", "GET"]) def routes_fermees(): cur = con.cursor() # 获取前端传递的where参数,默认空字符串 where_clause = request.form.get('where', '') # 基础SQL语句 sql = """ select json_build_object( 'type', 'FeatureCollection', 'features', json_agg(ST_AsGeoJSON(routes_fermees_adn.*)::json) ) as geojson from routes_fermees_adn """ # 追加WHERE子句(如果有过滤条件) if where_clause: sql += f" WHERE {where_clause}" try: cur.execute(sql) result = cur.fetchone()[0] # 无匹配数据时返回空的FeatureCollection,避免Leaflet报错 if result is None: return jsonify({"type": "FeatureCollection", "features": []}) return result except Exception as e: con.rollback() return "ERROR" finally: cur.close()
额外提示
- SQL注入风险:当前直接拼接
where_clause存在安全隐患,建议优化为参数化查询。例如前端传递dep数组,后端用IN (%s)并传入参数列表。 - 请求方式一致性:JS代码设置
type: 'POST'但实际请求显示为GET,需确保前后端请求方式统一,若改为GET则需用request.args.get获取参数。
内容的提问来源于stack exchange,提问作者Matthieu L
相关产品推荐
相关产品推荐

