2009-02-18 18 views
12

Ho geodjango in esecuzione utilizzando openlayers e OpenStreetMaps con l'app di amministrazione.Come visualizzare i dati utilizzando gli openlayer con OpenStreetMap in geodjango?

Ora voglio scrivere alcune viste per visualizzare i dati. Fondamentalmente, voglio solo aggiungere una lista di punti (visti nell'amministratore) alla mappa.

Geodjango sembra utilizzare un file speciale per fare la sua magia nell'amministratore. C'è un buon modo per interfacciarti con questo?

Come posso scrivere una vista/modello per visualizzare i dati di geodjango su una finestra della mappa stradale aperta, come si vede nell'amministratore?

Al momento, sto scavando nel file openlayers.js e api in cerca di una soluzione 'facile'. (Non ho esperienza js, quindi ci vorrà del tempo.)

Il modo corrente che posso vedere per fare ciò è aggiungere il seguente come modello e usare django per aggiungere il codice necessario per visualizzare i punti. (Basato sul esempio 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> 

E 'questo come si fa, o c'è un modo migliore?

risposta

2

Penso che la soluzione sia praticabile e probabilmente l'approccio più semplice. Basta templatizzare il javascript e utilizzare Django per iniettare i tuoi punti dati mentre il modello viene renderizzato.

Se si desidera ottenere più fantasia, è possibile avere una vista Django che serve i punti dati come JSON (application/json) e quindi utilizzare AJAX per richiamare e recuperare i dati in base agli eventi che si verificano nel browser . Se si desidera che la propria applicazione sia altamente interattiva al di sopra e al di là di quanto offerto da OpenLayers, ciò potrebbe valerne la complessità aggiuntiva, ma ovviamente tutto dipende dalle esigenze dell'applicazione.

+0

Penso che il metodo migliore è quello di creare una vista Django che restituisce l'oggetto JSON necessaria per i dati necessari. – monkut

4

Un'altra soluzione è creare un modulo che utilizzi il widget di amministrazione di GeoDjango.

Per fare questo, ho:

Setup un GeneratePolygonAdminClass:

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

casi in cui è costruito il modulo:

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 

popolamento il widget del 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 

basato sul codice: http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/admin/options.py?rev=7980

Sembra che sia possibile utilizzare l'opzione extra_js per includere OpenStreetMap (non l'ho provato).

1

Si potrebbe considerare l'utilizzo di FloppyForms. Alla fine, di solito finisco per personalizzare la soluzione per le mie esigenze, ma è un buon modo per iniziare.

2

Questo è abbastanza vecchio, e mi wouldn' andare in giro a creare un modello di hack come pensavo all'inizio. Ora userei leaflet.js con una richiesta Ajax su una vista di Django che restituisce geojson a un foglio di geojson.

Questo rende il lato django super facile.

Esempio 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') 
Problemi correlati