使用Leaflet结合modal fade输入经纬度展示地图点位的问题排查
1. 修复模型属性冲突
你在Even模型里同时定义了longitude、latitude字段和同名的@property属性,会出现属性读取冲突,删掉冗余的字段定义即可:
# models.py class Even(models.Model): name = models.CharField(max_length=20) date_reported = models.DateField() # 删掉下面两个重复的字段定义,已经通过property从geom读取 # longitude = models.FloatField(null=True, blank=True) # latitude = models.FloatField(null=True, blank=True) geom = models.PointField(srid=4326, null=True, blank=True,) @property def longitude(self): return self.geom.x @property def latitude(self): return self.geom.y def __str__(self): return self.name
2. 修复路由参数缺失问题
报错EvenementDataPoint() missing 2 required positional arguments是因为你的路由没有给视图函数预留经纬度参数占位符,调整urls.py:
# urls.py urlpatterns = [ # 新增经纬度参数占位符,匹配float类型 path('evenement_point/<float:longitude>/<float:latitude>/', views.EvenementDataPoint,name="evenement_point"), # 不需要单独的地图页面路由,可以直接删掉 # path('evenement_map_point/', views.evenement_map_point,name="evenement_map_point"), ]
3. 调整Modal提交逻辑,改为异步提交
你之前用同步表单提交,会直接跳转页面,要么显示纯JSON要么跳转到空白地图页,改为AJAX异步提交即可在当前页的地图上直接渲染点位:
先修改modal的表单结构,取消同步提交:
<!-- index.html modal部分 --> <div class="container-fluid"> <div class="modal fade" id="evenmapPoint"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">查询菜单</h4> <button type="button" class="close" data-dismiss="modal">×</button> </div> <div class="modal-body"> <form id="evenmappoint"> {% csrf_token %} <div class="row"> <div class="col-sm-6"> <div class="form-group"> <input class="form-control valid" name="longitude" type="number" step="any" placeholder="输入经度"> </div> </div> <div class="col-sm-6"> <div class="form-group"> <input class="form-control valid" name="latitude" type="number" step="any" placeholder="输入纬度"> </div> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" id="searchBtn" class="btn btn-success">查询</button> <button type="button" class="btn btn-danger" data-dismiss="modal">关闭</button> </div> </div> </div> </div>
新增异步提交和地图渲染的JS逻辑:
确保你的index.html已经正确初始化了Leaflet地图对象(变量名为map),加入以下JS代码:
let pointLayer = null; // 存储点位图层,避免重复查询叠加多个图层 document.getElementById('searchBtn').addEventListener('click', function() { // 读取表单输入的经纬度 const lng = document.querySelector('input[name="longitude"]').value; const lat = document.querySelector('input[name="latitude"]').value; if (!lng || !lat) return alert('请输入完整的经纬度'); // 清空上一次查询的点位 if (pointLayer) map.removeLayer(pointLayer); // 拼接GeoJSON接口地址,传入经纬度参数 const geoUrl = `/evenement_point/${lng}/${lat}/`; // 请求数据渲染图层 pointLayer = new L.GeoJSON.AJAX(geoUrl, { pointToLayer: function (feature, latlng) { return L.marker(latlng, { icon: L.icon({ iconUrl: "/static/img/icons/red.png", iconSize: [28, 32], iconAnchor: [12, 28], popupAnchor: [0, -25] }), title: feature.properties.name, riseOnHover: true }); }, onEachFeature: function (feature, layer) { const content = `<table class='table table-striped table-bordered table-condensed'> <tr><th>名称</th><td>${feature.properties.name}</td></tr> <tr><th>上报日期</th><td>${feature.properties.date_reported}</td></tr> </table>`; layer.bindPopup(content); } }).addTo(map); // 提交后关闭弹窗 $('#evenmapPoint').modal('hide'); })
4. 优化视图返回逻辑
删除不需要的evenement_map_point视图,优化EvenementDataPoint的序列化配置,避免字段缺失:
# views.py from django.contrib.gis.geos import Point from django.core.serializers import serialize from django.http import HttpResponse def EvenementDataPoint(request, longitude, latitude): ref_location = Point(float(longitude), float(latitude), srid=4326) # 注意:浮点坐标完全相等匹配很容易因为精度问题查不到结果,建议换成范围查询,比如查询100米内的点位 # queryset = Even.objects.filter(geom__distance_lte=(ref_location, 100)) queryset = Even.objects.filter(geom=ref_location) # 明确指定几何字段和返回属性 geojson = serialize('geojson', queryset, geometry_field='geom', fields=('name', 'date_reported')) return HttpResponse(geojson, content_type='application/json')
额外说明
- modal调用的接口需要返回GeoJSON格式数据,不需要返回HTML,所有渲染逻辑都在当前页完成,不需要跳转新页面
- 注意经纬度的顺序,GeoJSON和Point对象的参数是
(经度, 纬度),Leaflet的Marker参数是(纬度, 经度),不要搞混 - 之前单独的
even_map_point.html页面可以直接删除,所有逻辑都在首页完成
内容的提问来源于stack exchange,提问作者Saliha Alger
相关产品推荐
相关产品推荐

