Как отображать данные с помощью openlayers с OpenStreetMap в geodjango?
У меня работает geodjango с помощью openlayers и OpenStreetMaps с приложением администратора.
Теперь я хочу написать некоторые представления для отображения данных. В принципе, я просто хочу добавить список точек (см. Админ) на карту.
Geodjango, похоже, использует специальный файл openlayers.js, чтобы сделать это волшебство в админе. Есть ли хороший способ взаимодействовать с этим?
Как я могу написать view/template для отображения данных geodjango в окне открытой уличной карты, как видно из admin?
В настоящий момент я врываюсь в файл openlayers.js и 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>
Как это делается, или есть лучший способ?
Ответы
Ответ 1
Я думаю, что ваше решение работоспособно и, вероятно, самый простой подход. Просто templatize javascript и используйте Django для ввода ваших точек данных при визуализации шаблона.
Если вы хотите получить более интересное, вы можете иметь представление Django, которое обслуживало точки данных как JSON (application/json), а затем использовать AJAX для перезвона и получения данных на основе событий, которые происходят в браузере. Если вы хотите, чтобы ваше приложение было очень интерактивным, помимо того, что предлагает OpenLayers, это может стоить дополнительной сложности, но, конечно, все зависит от потребностей вашего приложения.
Ответ 2
Другим решением является создание формы, в которой используется виджет администратора GeoDjango.
Для этого I:
Настройка генератораPolygonAdminClass:
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 (я не тестировал это).
Ответ 3
Это довольно старый, и я бы не стал создавать шаблонный хак, как я изначально думал. Теперь я бы использовал leaflet.js с запросом ajax в представлении django, который возвращает geojson на слой geojson листовки.
Это делает игру django очень простой.
Пример просмотра 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 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')
Ответ 4
Вы можете использовать FloppyForms. В конце концов, я обычно настраиваю решение на свои собственные нужды, но это хороший способ начать работу.
Ответ 5
Ознакомьтесь с этим руководством из проекта geodjango-basic-apps:
http://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop
возможно, вам не нужно взламывать свой собственный javascript еще