Как отображать данные с помощью openlayers с OpenStreetMap в geodjango?

У меня работает geodjango с использованием openlayers и OpenStreetMaps с приложением администратора.

Теперь я хочу написать несколько представлений для отображения данных. В принципе, я просто хочу добавить список точек (видимых в админке) на карту.

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>

Это так делается или есть способ лучше?


person monkut    schedule 18.02.2009    source источник


Ответы (5)


Я думаю, что ваше решение работоспособно и, вероятно, самый простой подход. Просто создайте шаблон javascript и используйте Django для ввода точек данных по мере отображения шаблона.

Если вы хотите поизобретать, у вас может быть представление Django, которое обслуживает точки данных как JSON (application/json), а затем использует AJAX для обратного вызова и получения данных на основе событий, происходящих в браузере. Если вы хотите, чтобы ваше приложение было более интерактивным, чем то, что предоставляет OpenLayers, это может стоить дополнительной сложности, но, конечно, все зависит от потребностей вашего приложения.

person Joe Holloway    schedule 20.02.2009
comment
Я думаю, что лучший способ — создать представление django, которое возвращает необходимый объект JSON для необходимых данных. - person monkut; 13.01.2012

Другое решение — создать форму, использующую виджет 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 (я не проверял это).

person Gregory Roby    schedule 29.12.2009

Это довольно старо, и я бы не стал создавать взлом шаблона, как я изначально думал. Теперь я бы использовал leaflet.js с запросом ajax к представлению django, которое возвращает geojson в листовку. геоджсон слой.

Это делает сторону 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')
person monkut    schedule 13.12.2012

Вы можете использовать FloppyForms. В конце концов, я обычно заканчиваю тем, что настраиваю решение под свои нужды, но это хороший способ начать работу.

person ivy    schedule 03.10.2011

Ознакомьтесь с этим руководством в проекте geodjango-basic-apps:
http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop

возможно, вам пока не нужно ломать свой собственный javascript

person Anentropic    schedule 12.01.2012