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

StackOverflow https://stackoverflow.com/questions/559431

Вопрос

У меня работает geodjango, используя открытые слои и OpenStreetMaps с приложением администратора.

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

Геоджанго, похоже, использует особенный openlayers.js файл, чтобы сделать это волшебство в админке.Есть ли хороший способ взаимодействия с этим?

Как я могу написать представление/шаблон для отображения данных геоджанго в открытом окне карты улиц, как это видно в администраторе?

На данный момент я копаюсь в openlayers.js file и 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>

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

Это было полезно?

Решение

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

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

Другие советы

Другое решение — создать форму, использующую виджет администратора GeoDjango.

Для этого я:

Настройте 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 (я это не проверял).

Это довольно старая версия, и я бы не стал создавать хак шаблона, как я изначально думал.Сейчас я бы использовал листовка.js с запросом ajax к представлению django, которое возвращает geojson в слой 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')

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top