2009-02-18 28 views
12

Mam geodjango działające przy użyciu openlayers i OpenStreetMaps z aplikacją administratora.Jak wyświetlić dane za pomocą otwartych warstw z OpenStreetMap w geodjango?

Teraz chcę napisać kilka widoków, aby wyświetlić dane. Zasadniczo, chcę tylko dodać listę punktów (widoczną w adminie) do mapy.

Wygląda na to, że Geodjango używa specjalnego pliku openlayers.js, aby zrobić to magicznie w administracji. Czy istnieje dobry sposób na połączenie z tym?

Jak mogę napisać widok/szablon, aby wyświetlić dane geodjango w oknie otwartej mapy ulic, jak widać u administratora?

W tej chwili przekopuję się do pliku openlayers.js, a api szuka "łatwego" rozwiązania. (Nie mam doświadczenia js, więc zajmuje to trochę czasu.)

Obecny sposób, jaki mogę zobaczyć, to dodać poniższe jako szablon i użyć django do dodania kodu potrzebnego do wyświetlenia punktów. (Bazując na przykładzie 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> 

Czy to jak to się robi, czy jest jakiś lepszy sposób?

Odpowiedz

2

Myślę, że twoje rozwiązanie jest możliwe do zrealizowania i prawdopodobnie najłatwiejsze. Po prostu zmień szablon na javascript i użyj Django, aby wstrzyknąć punkty danych podczas renderowania szablonu.

Jeśli chcesz być bardziej zaawansowany, możesz mieć widok Django, który wyświetlił punkty danych jako JSON (application/json), a następnie użyć AJAX do oddzwonienia i pobrania danych w oparciu o zdarzenia zachodzące w przeglądarce . Jeśli chcesz, aby aplikacja była wysoce interaktywna, wykraczająca poza to, co oferuje OpenLayers, może to być warte większej złożoności, ale oczywiście wszystko zależy od potrzeb Twojej aplikacji.

+0

Myślę, że najlepszą metodą jest utworzyć widok Django, który zwraca niezbędną obiekt JSON dla niezbędnych danych. – monkut

4

Innym rozwiązaniem jest utworzenie formularza wykorzystującego widget Administrator GeoDjango.

Aby to zrobić, I:

Skonfiguruj GeneratePolygonAdminClass:

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

Jeżeli formularz jest zbudowany:

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 

Zapełnianie widget w postaci:

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 

Na podstawie pod kodem: http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/admin/options.py?rev=7980

Wygląda na to, że możesz użyć opcji extra_js do dołączenia OpenStreetMap (tego nie testowałem).

1

Możesz rozważyć użycie FloppyForms. W końcu zwykle dostosowuję rozwiązanie do własnych potrzeb, ale jest to dobry sposób na rozpoczęcie pracy.

2

Jest to dość stary, a ja wouldn” t dookoła tworzenia szablonu hack, tak jak początkowo myślałem. Teraz chciałbym użyć leaflet.js z żądaniem ajax do widoku django, który zwraca geojsona do warstwy geojsona ulotki.

To sprawia, że ​​strona django jest bardzo łatwa.

Próbka Django Widok:

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