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.
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.
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="http://maps.google.com/maps/api/staticmap?sensor=false&size=400x400&markers=size:mid|color:red|" + address + "," + city + "," + state + "," + zip;
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):
self.use_google_maps = False;
image = urllib.urlretrieve("http://maps.google.com/maps/api/staticmap? sensor=false&size=400x400&markers=size:mid|color:red|" + \
self.address + "," + self.city + "," + self.state + "," + self.zip)
self.map.save(self.company_name + "_map.jpg", File(open(image)))
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.