简体   繁体   English

如何在geodjango中使用OpenStreetMap的openlayers显示数据?

[英]How to display data using openlayers with OpenStreetMap in geodjango?

I've got geodjango running using openlayers and OpenStreetMaps with the admin app. 我已经使用openlayersOpenStreetMaps运行管理应用程序运行geodjango。

Now I want to write some views to display the data. 现在我想写一些视图来显示数据。 Basically, I just want to add a list of points (seen in the admin) to the map. 基本上,我只想在地图中添加一个点列表(在管理员中看到)。

Geodjango appears to use a special openlayers.js file to do it's magic in the admin. Geodjango似乎使用了一个特殊的 openlayers.js文件来管理它。 Is there a good way to interface with this? 有没有一种很好的方式与此接口?

How can I write a view/template to display the geodjango data on a open street map window, as is seen in the admin? 如何编写视图/模板以在打开的街道地图窗口中显示geodjango数据,如管理员所示?

At the moment, I'm digging into the openlayers.js file and api looking for an 'easy' solution. 目前,我正在挖掘openlayers.js文件和api寻找一个“简单”的解决方案。 (I don't have js experience so this is taking some time.) (我没有经验,所以这需要一些时间。)

The current way I can see to do this is add the following as a template, and use django to add the code needed to display the points. 我可以看到的当前方式是将以下内容添加为模板,并使用django添加显示点所需的代码。 (Based on the example 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>

Is this how it's done, or is there a better way? 它是如何完成的,还是有更好的方法?

Another solution is to create a form that utilizes the GeoDjango Admin widget. 另一种解决方案是创建一个使用GeoDjango Admin小部件的表单。

To do this, I: 为此,我:

Setup a GeneratePolygonAdminClass: 设置GeneratePolygonAdminClass:

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

Where the form is built: 表格的构建地点:

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

Populating the widget of the 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

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

It looks like you can use the extra_js option to include OpenStreetMap (I have not tested this). 看起来你可以使用extra_js选项来包含OpenStreetMap(我还没有测试过这个)。

This is quite old, and I wouldn't go around creating a template hack as I originally was thinking. 这是相当古老的,我不会像我最初想的那样创建模板黑客。 Now I would use leaflet.js with an ajax request to a django view that returns geojson to a leaflet geojson layer. 现在我将使用leaflet.js用Ajax请求到返回以GeoJSON到小叶以GeoJSON层Django视图。

This makes the django side super easy. 这使得django方面非常容易。

Sample Django View: 示例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')

I think your solution is workable and probably the easiest approach. 我认为您的解决方案是可行的,可能是最简单的方法。 Just templatize the javascript and use Django to inject your data points as the template is rendered. 只需模板化javascript并使用Django在渲染模板时注入数据点。

If you wanted to get fancier, you could have a Django view that served up the data points as JSON (application/json) and then use AJAX to call back and retrieve the data based on events that are happening in the browser. 如果你想变得更加漂亮,你可以拥有一个Django视图,它将数据点作为JSON(application / json)提供,然后使用AJAX根据浏览器中发生的事件回调和检索数据。 If you want your application to be highly interactive above and beyond what OpenLayers provides, this might be worth the added complexity, but of course it all depends on the needs of your application. 如果您希望您的应用程序在OpenLayers提供的内容之外具有高度交互性,那么这可能值得增加复杂性,但当然这一切都取决于您的应用程序的需求。

You could consider using FloppyForms . 您可以考虑使用FloppyForms In the end, I usually end up customizing the solution to my own needs, but it's a nice way to get started. 最后,我通常最终根据自己的需求定制解决方案,但这是一个很好的入门方式。

Checkout this tutorial from the geodjango-basic-apps project: 从geodjango-basic-apps项目中查看本教程:
http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop

maybe you don't have to hack up your own javascript just yet 也许你还没有破解自己的javascript

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM