Adding Geolocation Support to GeoDjango Admin

GeoDjango is awesome. It’s one of those frameworks that does an amazing amount of heavy lifting for you behind the scenes so you can just focus on your implementation. There was one thing that has been bugging me about it since day one though: the map picker tool used in the administration area doesn’t focus on your current location automatically. It simply gets initialized somewhere around Cameroon, and you have to pan and zoom your way around the world every time you want to add a single point, or polygon, most likely near where you are.

Adding geolocation support to this map has been surprisingly easy. Google Chrome, Firefox, and now Safari 5 all support geolocation, through W3C Geolocation Standard. Google Maps API documentation includes a very handy JavaScript snippet that you can use to activate this feature, and it even has fallback support for browsers that have Google Gears installed, which has its own geolocation support.

Without further ado, let’s get into the code. First, I switched the GeoDjango admin to use a Google Maps layer instead of the default Open Street Maps one. It’s simply better in terms of visuals and readability, and people are much more used to it. I followed the snippet here and added the google.html and google.js files under templates/gis/admin.

After this, all I had to do was modify the google.js file to include geolocation support. The only gotcha here was using the transform call on OpenLayers.LonLat object to convert it into the correct projection format. Otherwise just passing the coordinates simply doesn’t work.

{% extends "gis/admin/openlayers.js" %}
 
{% block base_layer %}new OpenLayers.Layer.Google("Google Base Layer", {
'type': G_NORMAL_MAP,
'sphericalMercator': true
});
 
{% endblock %}
 

{% block controls %}
 
{{ block.super }}
 
if (!wkt) {
var zoomLevel = 14;

// Try W3C Geolocation method (Preferred)
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
{{ module }}.map.setCenter(new OpenLayers.LonLat(
position.coords.longitude, position.coords.latitude
).transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
), zoomLevel);
}, function() {
// Location could not be found (probably denied by user)
});
} else if (google.gears) {
// Try Google Gears Geolocation
var geo = google.gears.factory.create('beta.geolocation');
 
geo.getCurrentPosition(function(position) {
{{ module }}.map.setCenter(new OpenLayers.LonLat(
position.longitude,
position.latitude), zoomLevel);
}, function() {
// Location could not be found (probably denied by user)
});
} else {
// Browser doesn't support Geolocation
}
}
 
{% endblock %}

There you go, this will focus on your current location (after asking for your permission, of course), if you don’t have any points or polygons defined on the map. If you do, then it will simply focus on their boundaries.

Comments (4)