Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering spatial data of GeoQuerySet in a custom view on GeoDjango

I have just started my first project on GeoDjango.

As 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.

like image 234
Dmitry Lebedev Avatar asked Jun 14 '10 00:06

Dmitry Lebedev


1 Answers

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

  1. Create a Django view, using vectorformats to return your data as GeoJSON
  2. Create a separate view, which returns an HTML page like the OpenLayers example linked, with the modifications shown in the code sample.
  3. That view serves the HTML page that loads your GeoJSON data and parses it.
like image 188
Christopher Schmidt Avatar answered Sep 27 '22 15:09

Christopher Schmidt