On the Map

So far we’ve done all kinds of wearying and information – but never left a Python console. I suppose it’s time we fall into the web mapping world and look at our options.

On the left of the easy-to-hard scale is Google Maps, API v2. This is the deprecated version, but is the only frontend generation available to us out of the box. It’s not mentioned in the documentation, but is well represented in the class’ docstring. (django.contrib.gis.maps.google)

Follow the doctoring to get your template set up appropriately.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
{{ google.xhtml }}
<head>
 <title>Google Maps via GeoDjango</title>
 {{ google.style }}
 {{ google.scripts }}
</head>
{{ google.body }}
<div id="{{ google.dom_id }}" style="width:600px;height:400px;"></div>
</body>
</html>

We create markers from the points we have with this:

Then instantiate the map with a markers kwarg (you can include key=’api_key_here’ in the class instantiation or it will fall back to settings.GOOGLE_MAPS_API_KEY), pass it into the template and watch in amazement as a map materializes before your eyes!

from django.contrib.gis.geos import Point
from django.contrib.gis.maps.google import GoogleMap, GMarker, GPolygon
from django.contrib.gis.measure import D

from uscampgrounds.models import Campground

def gmap2(request):
	campgrounds = Campground.objects.filter(point__distance_lte=(Point((-94, 37)), D(mi=100)))

	markers = []
	for campground in campgrounds:
		markers.append(GMarker(campground.point, title=campground.name))

	the_map = GoogleMap(markers=markers)

	return render_to_response('googlemap.html', {
		'google': the_map,
	}, context_instance=RequestContext(request))

You can do this with polygons too, as this code illustrates.

from django.contrib.gis.geos import Point
from django.contrib.gis.maps.google import GoogleMap, GMarker, GPolygon
from django.contrib.gis.measure import D

from tigerline.models import State

def gmap2_poly(request):
	states = State.objects.filter(mpoly__distance_lte=(Point((-94, 37)), D(mi=100)))

	polygons = []
	for state in states:
		polygons.append(GPolygon(state.mpoly[0].simplify()))

	the_map = GoogleMap(polygons=polygons)

	return render_to_response('googlemap.html', {
		'google': the_map,
	}, context_instance=RequestContext(request))

The resulting HTML, even after running simplify() on the geometry, is 2.4MB so I won’t display it here – but here’s a link. Warning: displaying polygons gets big. I’m asking for trouble here, after all – every single point that makes up the boundary of four states is going to be a bunch.

django.contrib.gis.maps.google is great for quick, don’t need a lot of details or fancy overlays maps. But it leaves out an easy way to do click events on markers and labeling, and API keys are inconvenient.

IF you do need onClick events, infoWindows from markers or any of that stuff there are hacks – but it involves looping over the items in the template as well and generating JavaScript that infers what it knows this map generation code will name things. Best to bite the bullet and build API v3 code in a template on your own (coming soon!)

Leave a Reply

Your email address will not be published. Required fields are marked *