2009-02-18 12 views
12

Ich habe geodjango läuft mit openlayers und OpenStreetMaps mit der Admin-App.Wie kann man Daten mit OpenStreetMap im Geodjango anzeigen?

Jetzt möchte ich einige Ansichten schreiben, um die Daten anzuzeigen. Im Grunde möchte ich nur eine Liste von Punkten (im Admin angezeigt) zur Karte hinzufügen.

Geodjango scheint eine spezielleopenlayers.js Datei zu verwenden, um es in den Admin magisch zu machen. Gibt es eine gute Möglichkeit, damit zu interagieren?

Wie kann ich eine Ansicht/Vorlage schreiben, um die Geodjango-Daten in einem geöffneten Straßenkartenfenster anzuzeigen, wie im Admin angezeigt?

Im Moment, graben wir in die openlayers.js Datei und API suchen eine "einfache" Lösung. (Ich habe js Erfahrung, also dauert das einige Zeit.)

Die aktuelle Weise, die ich sehen kann, um dies zu tun, ist das folgende als Vorlage hinzufügen, und benutze django, um den Code hinzuzufügen, der benötigt wird, um die Punkte anzuzeigen. (Basierend auf dem Beispiel 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> 

Ist dies, wie es gemacht wird, oder gibt es einen besseren Weg?

Antwort

2

Ich denke, Ihre Lösung ist praktikabel und wahrscheinlich der einfachste Ansatz. Justlatieren Sie das Javascript und verwenden Sie Django, um Ihre Datenpunkte zu injizieren, während die Vorlage gerendert wird.

Wenn Sie schicker werden möchten, könnten Sie eine Django-Ansicht haben, die die Datenpunkte als JSON (application/json) ausgibt und dann AJAX zum Zurückrufen und Abrufen der Daten basierend auf Ereignissen im Browser verwendet . Wenn Sie möchten, dass Ihre Anwendung über das, was OpenLayers bietet, hochgradig interaktiv ist, könnte dies die zusätzliche Komplexität wert sein, aber natürlich hängt alles von den Anforderungen Ihrer Anwendung ab.

+0

Ich denke, die beste Methode, eine django Ansicht zu erstellen, die die notwendige JSON-Objekt für die notwendigen Daten zurückgibt. – monkut

4

Eine andere Lösung besteht darin, ein Formular zu erstellen, das das GeoDjango Admin-Widget verwendet.

Um dies zu tun, ich:

-Setup ein GeneratePolygonAdminClass:

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

Wo die Form gebaut wird:

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 

Bestücken das Widget der 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 

Basiert auf dem Code um: http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/admin/options.py?rev=7980

Es sieht so aus, als ob Sie die Option extra_js verwenden können, um OpenStreetMap einzuschließen (ich habe das nicht getestet).

1

Sie könnten FloppyForms verwenden. Am Ende fertige ich normalerweise die Lösung an meine eigenen Bedürfnisse an, aber es ist ein guter Einstieg.

2

Das ist ziemlich alt, und ich wouldn‘ Ich gehe herum und erstelle einen Template-Hack, wie ich ursprünglich gedacht habe. Jetzt würde ich leaflet.js mit einer Ajax-Anfrage an eine Django-Ansicht verwenden, die Geojson an eine Leaflet-Geojson-Ebene zurückgibt.

Dies macht die Django-Seite super einfach.

Beispiel Django Ausblick:

# -*- 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') 
Verwandte Themen