You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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">&times;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 07:15:04