Django and Google Maps

Adding a Google Maps address preview to the Django admin interface.

Last post I wrote about extending the Django Admin interface by adding a little dynamic data to the help_text field. For more advanced things you need to customize the html widget itself.

One thing I want to do is have a Django model automatically get a Google Map of the address I have stored and save this file. For my purposes though I don’t want this to be automatic, I’d rather an admin user check the map first then decide to overwrite any previous map file. I’ll extend the a widget to get this effect.

First I need a preview box. I want to insert some extra html, I’m actually going to put this into a checkbox form, you will see why later. I need to override the render def on the widget to add some code.

class MapImageWidget(forms.CheckboxInput):
def render(self, name, value, attrs=None):
output = []
output.append(super(MapImageWidget, self).render(name, value, attrs))
output.append("If checked, the above map file will be overwritten with Google Maps.<table><tr><td><a href=\"javascript:get_map()\">Preview Google Maps</a></td></tr><tr><td> <iframe width=\"400px\" height=\"400px\" name=\"mapframe\"></iframe> </td></tr></table>")

return mark_safe(u''.join(output))

I’m using Google Maps static maps url to get my previews. I made a javascript function called get_map to look up the url based on the address field on my model. I want it to actually use the currently typed in address rather than some ajax solution which may get the currently saved address.

function get_map(){
var address = document.getElementById("id_address").value;
var city = document.getElementById("id_city").value;
var state = document.getElementById("id_state").value;
var zip = document.getElementById("id_zip").value;
parent.mapframe.location="|color:red|" + address + "," + city + "," + state + "," + zip;

I put the javascript into my change_form.html admin template. This function is only for previewing by the user and has nothing to do with actually saving my map image. For that I have a checkbox as in this screen shot

Maps preview in admin edit page

When the user checks off the box, Django will know to get that image and set it to the map ImageField. I do this by overriding the save function on my model.

def save(self, *args, **kwargs):
if (self.use_google_maps):
self.use_google_maps = False;
image = urllib.urlretrieve(" sensor=false&size=400x400&markers=size:mid|color:red|" + \
self.address + "," + + "," + self.state + "," + + "_map.jpg", File(open(image[0])))
super(Company, self).save(*args, **kwargs)

I use urllib to “wget” the file. This process will replace the previous practice of manually looking up maps, saving them, and uploading them. Of course if I trusted Google maps (or my addresses to be correct) I could just have it dynamically get that image when needed instead of storing the image file.