python下实现jsonp

本文介绍如何利用高德地图API结合Python后端实现热力图加载,并详细解释了jsonp数据格式及其前后端交互过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在高德地图加载热力图时,数据支持jsonp,通过python实现:

1、后台python:

# 通过jsonp格式返回热力图的数据
def heatjsonp(request):
    funcname = request.GET.get('callback')
    # print(funcname)
    content = '%s(%s)' % (funcname, heatdata())
    # print(content)
    return HttpResponse(content)
# 通过jsonp格式返回热力图的数据
def heatjsonp(request):
    funcname = request.GET.get('callback')
   # 收取前台的callback函数名:[27/Apr/2018 10:29:15] "GET /jsonpdata?callback=jsonp_490268_ HTTP/1.1" 200 748372
    # 这里是通过get方式传入的:callback=jsonp_490268_
 content = '%s(%s)' % (funcname, heatdata())
 # heatdata函数返回数据字典,直接作为字符串的一部分返回到前台(有点纳闷:数据字典转为字符串是怎么做到的,估计是%s替换时自动转的?)
 return HttpResponse(content)
 

# 二级函数,生成热力图基础数据
def heatdata():
    lnglat_set = LngLat.objects.all()
    heatmapdict = {}
    for lnglat in lnglat_set:
        celldatausage_set = CellDataUsage.objects.filter(cell__lnglat=lnglat)
        # 以下语句相当于group by begin
        sumusage = celldatausage_set.values_list('begin').annotate(Sum('up'), Sum('down'))
        for eachday in sumusage:
            updown = int(eachday[1] + eachday[2])
            begin = Begin.objects.filter(id=eachday[0]).first().begin.strftime('%Y-%m-%d')
            onedict = {"lng": float(lnglat.lng), "lat": float(lnglat.lat), "count": updown}
            if begin in heatmapdict:
                if type(heatmapdict[begin]) is list:
                    heatmapdict[begin].append(onedict)
                else:
                    heatmapdict[begin] = [onedict]
            else:
                heatmapdict[begin] = [onedict]
    # 将数据库查询结果另存为site-data.js文件,用于提高初始加载时,站点的显示速度,注意:字符集统一为utf-8
    f = codecs.open('static/javascript/data/heatmapdict.js', 'w', 'utf-8')
    f.write("var heatmapdict = %s" % heatmapdict)
    f.close()
    return heatmapdict

2、前台接收jsonp后,必须配合解析

返回给前台的数据为:

jsonp_490268_({'2017-09-18': [{'lng': 125.2875, 'lat': 42.269444, 'count': 18975}, ...]})

这是什么意思呢?

    其实时一个函数的调用,函数名为jsonp_490268_,参数为

{'2017-09-18': [{'lng': 125.2875, 'lat': 42.269444, 'count': 18975}, ...]}

参数就是原本想通过json格式返回的数据。

这个函数的函数名jsonp_490268_是前台调用jsonp时自动生成的,但是函数需要在前台定义:

//设置数据集:该数据为北京部分“公园”数据
heatmap.setDataSet({
    //data: heatmapData,
    data:'/jsonpdata',  // 通过jsonp格式请求数据
    dataParser: function(data){    // 这个函数就是jsonp返回时,执行的函数,它目前没有函数名,但实际执行时,使用的自动生成的函数名jsonp_490268_
        console.log(data);    // 这个函数的参数data就是{'2017-09-18': [{'lng': 125.2875, 'lat': 42.269444, 'count': 18975}, ...]}
        return data['2017-09-18'];//返回的对象结果应该与上面例子的data字段结构相同
    },
    max: 100
});

注意,每次调用时,函数名都会变。

前台代码:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>热力图</title>
    <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>
    <script type="text/javascript" src="/static/javascript/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="/static/javascript/preventCSRF.js"></script>
    <script src="http://webapi.amap.com/maps?v=1.4.6&key=348e60dba92f158e939c942cf20e3188"></script>
    <script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
    <script type="text/javascript" src="http://a.amap.com/jsapi_demos/static/resource/heatmapData.js"></script>
</head>
<body>
<div id="container"></div>
<div class="button-group">
    <input type="button" class="button" value="显示热力图0" οnclick="on1off2()"/>
    <input type="button" class="button" value="显示热力图1" οnclick="on2off1()"/>
</div>
<script>
    function on1off2() {
        heatmap.show();
        heatmap1.hide();
    }
    function on2off1() {
        heatmap.hide();
        heatmap1.show();
    }
    var map = new AMap.Map("container", {
        resizeEnable: true,
        center: [116.418261, 39.921984],
        zoom: 11
    });
    if (!isSupportCanvas()) {
        alert('热力图仅对支持canvas的浏览器适用,您所使用的浏览器不能使用热力图功能,请换个浏览器试试~')
    }
    //详细的参数,可以查看heatmap.js的文档 http://www.patrick-wied.at/static/heatmapjs/docs.html
    //参数说明如下:
    /* visible 热力图是否显示,默认为true
     * opacity 热力图的透明度,分别对应heatmap.js的minOpacity和maxOpacity
     * radius 势力图的每个点的半径大小
     * gradient  {JSON} 热力图的渐变区间 . gradient如下所示
     * {
     .2:'rgb(0, 255, 255)',
     .5:'rgb(0, 110, 255)',
     .8:'rgb(100, 0, 255)'
     }
     其中 key 表示插值的位置, 0-1
     value 为颜色值
     */

    var points =[
        {"lng":116.191031,"lat":39.988585,"count":90},
        {"lng":116.389275,"lat":39.925818,"count":91},
        {"lng":116.287444,"lat":39.810742,"count":92},
        {"lng":116.481707,"lat":39.940089,"count":83},
        {"lng":116.410588,"lat":39.880172,"count":74},
        {"lng":116.394816,"lat":39.91181,"count":85},
        {"lng":116.416002,"lat":39.952917,"count":96}
    ];

    var heatmap, heatmap1;
    /*
    heatmap = new AMap.Heatmap({map:map});    //在地图对象叠加热力图
    heatmap.setDataSet({data:points,max:100}); //设置热力图数据集
    heatmapsetMap(map);
    */
    map.plugin(["AMap.Heatmap"], function() {

        //初始化heatmap对象
        heatmap = new AMap.Heatmap(map, {
            radius: 25, //给定半径
            opacity: [0, 0.8]
        });
        heatmap1 = new AMap.Heatmap(map, {
            radius: 25, //给定半径
            opacity: [0, 0.8]
            /*,gradient:{
             0.5: 'blue',
             0.65: 'rgb(117,211,248)',
             0.7: 'rgb(0, 255, 0)',
             0.9: '#ffea00',
             1.0: 'red'
             }*/
        });
        /*
        console.log("a");
        $(function() {
            // 为防止CSRF(Cross-site request forgery)跨站请求伪造,发post请求时需要在cookie中创建随机码
            $.ajaxSetup({
                headers: { "X-CSRFToken": getCookie("csrftoken") }
            });
            console.log("b");
            $.post("/heatmapdata", {arg: "arg"}, function(data, status) {
                console.log(data, status);
                heatmap.setDataSet({
                    data: data['2017-09-18'],
                    max: 100000
                });
                heatmap1.setDataSet({data:data['2017-09-19'], max: 100000});
            });
        });
        */

        //设置数据集:该数据为北京部分“公园”数据
        heatmap.setDataSet({
            //data: heatmapData,
            data:'/jsonpdata',
            dataParser: function(data){
                console.log(data);
                return data['2017-09-18'];//返回的对象结果应该与上面例子的data字段结构相同
            },
            max: 100
        });
        //heatmap.setMap(map);

        //heatmap1 = new AMap.Heatmap({map:map});    //在地图对象叠加热力图
        heatmap1.setDataSet({data:points,max:100}); //设置热力图数据集
        //heatmap1.setMap(map);

    });

    //判断浏览区是否支持canvas
    function isSupportCanvas() {
        var elem = document.createElement('canvas');
        return !!(elem.getContext && elem.getContext('2d'));
    }
</script>
</body>
</html>
setDataSet(dataset:Object) 设置热力图展现的数据集,dataset数据集格式为:
{
  max: Number 权重的最大值,
  data: Array 坐标数据集
},
其中max不填则取数据集count最大值
例: {
  max: 100,
  data: [{lng: 116.405285, lat: 39.904989, count: 65},{}, …]
  }
也可以通过url来加载数据,格式为
{
  data:jsonp格式数据的服务地址URL,
  dataParser: 数据格式转换function//当jsonp返回结果和官方结构不一致的时候,用户可以传递一个函数用来进行数据格式转换;
}
例:
{
  data:'http://abc.com/jsonp.js',
  dataParser:function(data){
   return doSomthing(data);//返回的对象结果应该与上面例子的data字段结构相同
  }
}
http://lbs.amap.com/api/javascript-api/reference/layer#m_HeatmapOptions




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值