【问题标题】:How to display data using openlayers with OpenStreetMap in geodjango?如何在geodjango中使用带有OpenStreetMap的openlayers显示数据?
【发布时间】:2010-10-08 05:58:26
【问题描述】:

我已经通过管理应用程序使用openlayersOpenStreetMaps 运行geodjango。

现在我想写一些视图来显示数据。基本上,我只想将点列表(在管理员中看到)添加到地图中。

Geodjango 似乎使用了一个特殊 openlayers.js 文件来在管理中发挥它的魔力。有什么好的方法可以与之交互吗?

如何编写视图/模板以在打开的街道地图窗口上显示 geodjango 数据,就像在管理员中看到的那样?

目前,我正在深入研究 openlayers.js 文件和 api,以寻找“简单”的解决方案。 (我没有js经验,所以这需要一些时间。)

我可以看到的当前方法是将以下内容添加为模板,并使用 django 添加显示点所需的代码。 (以here为例)

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Draw Feature Example</title>

        <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
      <script type="text/javascript">
            var map;

            function init(){
                map = new OpenLayers.Map('map');
                var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
                        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
                map.addLayer(layer);

                /*
                 * Layer style
                 */
                // we want opaque external graphics and non-opaque internal graphics
                var layer_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
                layer_style.fillOpacity = 0.2;
                layer_style.graphicOpacity = 1;

                /*
                 * Blue style
                 */
                var style_blue = OpenLayers.Util.extend({}, layer_style);
                style_blue.strokeColor = "blue";
                style_blue.fillColor = "blue";
                style_blue.graphicName = "star";
                style_blue.pointRadius = 10;
                style_blue.strokeWidth = 3;
                style_blue.rotation = 45;
                style_blue.strokeLinecap = "butt";

                var vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", {style: layer_style});

                // create a point feature
                var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
                var pointFeature = new OpenLayers.Feature.Vector(point,null,style_blue);
                // Add additional points/features here via django

                map.addLayer(vectorLayer);
                map.setCenter(new OpenLayers.LonLat(point.x, point.y), 5);
                vectorLayer.addFeatures([pointFeature]);
            }
        </script>
    </head>
    <body onload="init()">
        <div id="map" class="smallmap"></div>
    </body>
</html>

是这样完成的,还是有更好的方法?

【问题讨论】:

    标签: python mapping openlayers geodjango


    【解决方案1】:

    我认为您的解决方案是可行的,并且可能是最简单的方法。只需模板化 javascript 并使用 Django 在模板呈现时注入您的数据点。

    如果您想变得更高级,您可以使用 Django 视图将数据点作为 JSON (application/json) 提供,然后使用 AJAX 回调并根据浏览器中发生的事件检索数据。如果您希望您的应用程序在 OpenLayers 提供的功能之外具有高度交互性,那么增加复杂性可能值得,但当然这完全取决于您的应用程序的需求。

    【讨论】:

    • 我认为最好的方法是创建一个 django 视图,为必要的数据返回必要的 JSON 对象。
    【解决方案2】:

    另一个解决方案是创建一个利用 GeoDjango Admin 小部件的表单。

    为此,我:

    设置 GeneratePolygonAdminClass:

    class GeneratePolygonAdmin(admin.GeoModelAdmin):
        list_filter=('polygon',)
        list_display=('object', 'polygon')
    

    表单的构建位置:

    geoAdmin=GeneratePolygonAdmin(ModelWithPolygonField, admin.site)
    PolygonFormField=GeneratePolygon._meta.get_field('Polygon')
    PolygonWidget=geoAdmin.get_map_widget(PolygonFormField)
    Dict['Polygon']=forms.CharField(widget=PolygonWidget())  #In this case, I am creating a Dict to use for a dynamic form
    

    填充表单的小部件:

    def SetupPolygonWidget(form, LayerName, MapFileName, DefaultPolygon=''):
        form.setData({'Polygon':DefaultPolygon})
        form.fields['Polygon'].widget.params['wms_layer']=LayerName
        form.fields['Polygon'].widget.params['wms_url']='/cgi-bin/mapserv?MAP=' + MapFileName
        form.fields['Polygon'].widget.params['default_lon']=-80.9
        form.fields['Polygon'].widget.params['default_lat']=33.7
        form.fields['Polygon'].widget.params['default_zoom']=11
        form.fields['Polygon'].widget.params['wms_name']=YOURWMSLayerName
        form.fields['Polygon'].widget.params['map_width']=800
        form.fields['Polygon'].widget.params['map_height']=600
        form.fields['Polygon'].widget.params['map_srid']=YOUR_SRID
        form.fields['Polygon'].widget.params['modifiable']=True
        form.fields['Polygon'].widget.params['map_options']={}
        form.fields['Polygon'].widget.params['map_options']['buffer'] = 0   
        return form
    

    基于以下代码: http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/admin/options.py?rev=7980

    看起来您可以使用 extra_js 选项来包含 OpenStreetMap(我还没有测试过)。

    【讨论】:

      【解决方案3】:

      您可以考虑使用FloppyForms。最后,我通常会根据自己的需要定制解决方案,但这是一种很好的入门方式。

      【讨论】:

        【解决方案4】:

        查看 geodjango-basic-apps 项目中的本教程:
        http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop

        也许您现在还不需要编写自己的 javascript

        【讨论】:

          【解决方案5】:

          这已经很老了,我不会像我最初的想法那样到处创建模板破解。现在我将使用leaflet.js 向django 视图发出ajax 请求,该视图将geojson 返回到传单geojson 层。

          这让 django 方面变得超级简单。

          示例 Django 视图:

          # -*- coding: utf-8 -*-
          '''
          '''
          import json
          from django.http import HttpResponse, HttpResponseBadRequest
          from django.contrib.gis.geos import Polygon
          
          from models import ResultLayer, MyModel
          
          def get_layer_polygons(request, layer_id):
              """
              Return the polygons for the given bbox (bounding box)
              """
              layer = ResultLayer.objects.get(id=layer_id)    
              bbox_raw = request.GET.get("bbox", None)
          
              # Make sure the incoming bounding box is correctly formed!
              bbox = None
              if bbox_raw and bbox_raw.count(",") == 3:        
                  bbox = [float(v) for v in bbox_raw.split(",")]     
              if not bbox:
                  msg = "Improperly formed or not given 'bbox' querystring option, should be in the format '?bbox=minlon,minlat,maxlon,maxlat'"
                  return HttpResponseBadRequest(msg)
          
              bbox_poly = Polygon.from_bbox(bbox)
              bbox_poly.srid = 900913 # google
              bbox_poly.transform(layer.srid) # transform to the layer's srid for querying  
          
              bin_size = int(bin_size)
              # build vector polygons from bin
              results = MyModel.objects.filter(layer=layer, poly__intersects=bbox_poly).transform(900913, field_name="poly")
              geojson_data = []
              for r in results:
                  # loading json in order to dump json list later
                  gjson = r.poly.geojson
                  py_gjson = json.loads(gjson)
                  geojson_data.append(py_gjson)
              return HttpResponse(json.dumps(geojson_data), mimetype='application/json')
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-10-11
            • 1970-01-01
            • 2023-03-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多