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

发布于 2024-07-14 07:32:28 字数 2971 浏览 8 评论 0原文

我已经使用 openlayers使用管理应用程序打开StreetMaps

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

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

如何编写视图/模板以在打开的街道地图窗口上显示 geodjango 数据,如管理中所示?

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

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

<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>

这是如何完成的,还是有一个更好的方法?

I've got geodjango running using openlayers and OpenStreetMaps with the admin app.

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. 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?

At the moment, I'm digging into the openlayers.js file and api looking for an 'easy' solution. (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. (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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

还如梦归 2024-07-21 07:32:28

另一个解决方案是创建一个使用 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 (我还没有测试过这个)。

Another solution is to create a form that utilizes the GeoDjango Admin widget.

To do this, I:

Setup a 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

It looks like you can use the extra_js option to include OpenStreetMap (I have not tested this).

甜`诱少女 2024-07-21 07:32:28

这已经很老了,我不会像我最初想的那样创建一个模板 hack。 现在我将使用 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')

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.

This makes the django side super easy.

Sample Django View:

# -*- 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')
ぽ尐不点ル 2024-07-21 07:32:28

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

如果您想要更高级,您可以使用 Django 视图,以 JSON (application/json) 形式提供数据点,然后使用 AJAX 根据浏览器中发生的事件回调和检索数据。 如果您希望您的应用程序具有高于 OpenLayers 提供的高度交互性,那么增加复杂性可能是值得的,但当然这一切都取决于您的应用程序的需求。

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.

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. 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.

萌吟 2024-07-21 07:32:28

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

You could consider using FloppyForms. In the end, I usually end up customizing the solution to my own needs, but it's a nice way to get started.

静待花开 2024-07-21 07:32:28

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

也许你还不必修改自己的 javascript

Checkout this tutorial from the geodjango-basic-apps project:
http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop

maybe you don't have to hack up your own javascript just yet

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文