2009-02-18 21 views
12

Tengo geodjango ejecutándose usando openlayers y OpenStreetMaps con la aplicación de administración.¿Cómo mostrar datos usando Openlayers con OpenStreetMap en geodjango?

Ahora quiero escribir algunas vistas para visualizar los datos. Básicamente, solo quiero agregar una lista de puntos (vistos en el administrador) al mapa.

Geodjango parece utilizar un archivo especial openlayers.js para hacer su magia en el administrador. ¿Hay una buena manera de interactuar con esto?

¿Cómo puedo escribir una vista/plantilla para mostrar los datos de geodjango en una ventana de mapa de calle abierta, como se ve en el administrador?

Por el momento, estoy investigando el archivo openlayers.js y estoy buscando una solución 'fácil'. (No tengo experiencia js así que esto toma algo de tiempo.)

La forma actual en que puedo ver esto es agregar lo siguiente como plantilla y usar django para agregar el código necesario para mostrar los puntos. (Basado en el ejemplo 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> 

¿Es así como se hace, o hay una mejor manera?

Respuesta

2

Creo que su solución es viable y, probablemente, el enfoque más fácil. Simplemente personalice el javascript y use Django para inyectar sus puntos de datos a medida que se procesa la plantilla.

Si quería ser más elegante, podría tener una vista de Django que sirviera los puntos de datos como JSON (aplicación/json) y luego usar AJAX para devolver y recuperar los datos en función de los eventos que están sucediendo en el navegador . Si desea que su aplicación sea altamente interactiva más allá de lo que ofrece OpenLayers, podría valer la pena la complejidad adicional, pero por supuesto todo depende de las necesidades de su aplicación.

+0

creo que el mejor método es crear una vista de Django que devuelve el objeto JSON necesario que los datos necesarios. – monkut

4

Otra solución es crear un formulario que utilice el widget GeoDjango Admin.

Para ello, I:

instalación de un GeneratePolygonAdminClass:

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

Cuando la forma se construye:

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 

Rellenar el widget de la forma:

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 

Basado en el código en: http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/admin/options.py?rev=7980

Parece que puede usar la opción extra_js para incluir OpenStreetMap (no lo he probado).

1

Podría considerar el uso de FloppyForms. Al final, generalmente termino personalizando la solución para mis propias necesidades, pero es una buena forma de comenzar.

2

Esto es bastante antiguo, y yo wouldn' voy por ahí creando un truco de plantilla como estaba originalmente pensando. Ahora usaría leaflet.js con una solicitud de ajax a una vista django que devuelva geojson a una capa geojson de folleto.

Esto hace que el lado de django sea muy fácil.

Muestra Django Vista:

# -*- 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') 
Cuestiones relacionadas