Rendering spatial data of GeoQuerySet in a custom view on GeoDjango
I have just started my first project on GeoDjango.
A开发者_开发技巧s a matter of fact, with GeoDjango powered Admin application we all have a great possibility to view/edit spatial data, associated with the current object.
The problem is that after the objects having been populated I need to render several objects' associated geometry at once on a single map. I might implement it as a model action, redirecting to a custom view. I just don't know, how to include the OpenLayers widget in the view and how to render there my compound geometry from my GeoQuerySet.
I would be very thankful for any hint from an experienced GeoDjango programmer.
Two halves of this question:
- How do I generate Geographic data that OpenLayers can read via Django?
- How do I consume this data with OpenLayers?
Generating Geographic Data
There are several different ways to generate geographic data in Django. Built in, you can use the .kml() or .json() methods on a queryset; doing so causes each returned instance to have a .json or .kml property which has the KML or JSON of the Geometry generated as a string.
You can then use this output in templates that use the {{feature.kml}} or {{feature.json}}. (The latter is somewhat difficult, because you would have to manually do the JSON encoding before it hit the template, a bit of an odd situation.)
Another option is to use a library to help you: specifically, vectorformats. (Google "featureserver vectorformats" for information, since I can only include one hyperlink.) Installed via PyPI/easy_install vectorformats, you can use the Django format:
>>> from vectorformats.Formats import Django, GeoJSON
>>> qs = Model.objects.filter(city="Cambridge")
>>> djf = Django.Django(geodjango="geometry", properties=['city', 'state'])
>>> geoj = GeoJSON.GeoJSON()
>>> s = geoj.encode(djf.decode(qs))
>>> print s
This string can be returned via an HTTPResponse to return a GeoJSON object. So, your view would wrap these 4 lines in a bit that generated a queryset (qs, here), and then returned an HttpResponse with the string.
Consuming Data
OpenLayers has 'format' objects which can read data: There are formats for GeoJSON and KML, as well as others.
You can load the data using standard XMLHttpRequest mechanisms then parse them with a format:
var f = new OpenLayers.Format.GeoJSON();
var features = f.read(req.responseText);
layer.addFeatures(features);
Alternatively, you can use the built in Protocol support to load remote data:
map = new OpenLayers.Map('map');
var wms = new OpenLayers.Layer.WMS(
"OpenLayers WMS", "http://labs.metacarta.com/wms/vmap0",
{layers: 'basic'}
);
var layer = new OpenLayers.Layer.Vector("GML", {
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: "/django/view/json/",
format: new OpenLayers.Format.GeoJSON()
})
});
map.addLayers([wms, layer]);
map.zoomToExtent(new OpenLayers.Bounds(
-3.92, 44.34, 4.87, 49.55
));
You can see in this example, that the 'url' points to your Django view; all the loading of data and parsing it according to the provided format is included. (You can see a similar example in the OpenLayers example for fixed behavior/http protocol.)
Putting it Together
- Create a Django view, using vectorformats to return your data as GeoJSON
- Create a separate view, which returns an HTML page like the OpenLayers example linked, with the modifications shown in the code sample.
- That view serves the HTML page that loads your GeoJSON data and parses it.
精彩评论