views:

576

answers:

2

In a django application I have the following model:

class Appointment(models.Model):
    #some other fields
    #address fields
    zipcode=models.CharField(max_length=5)
    address=models.CharField(max_length=120)
    latitude=models.FloatField()
    longitude=models.FloatField()

When I'm rendering an Appointment, I'm just putting a marker at the position specified by longitude and latitude with the address as text, however I need the latitude and longitude to do that.

Currently, latitude and longitude have to be entered manually in the admin backend, but opening Google Maps/OSM, searching for the address and entering latitude and longitude is work that shouldn't have to be done by hand, so I want to retrieve it through the Google Maps API (keyword Geocoding).

Ideally, I want a button "Get coordinates" next to the address, which, when pressed, starts a Geocoding request and fills in latitude and longitude when the address is unambiguous and presents a map with the results and fills in the coordinates when the user clicks on the right marker.

I know how to do that, but I'm not sure how I should insert the markup and the code into the admin backend.

Some things I already considered but don't want to do as they don't seem natural or seem to be too much work for such a simple task:

  • putting the code in the address field's description in field_options in a class derived from admin.ModelAdmin
  • putting everything address related in a separate model and using a custom form (with a separate template
  • create an address picker widget
  • use GeoDjango
+1  A: 

There are several ways of doing this. You already mentioned some yourself.

An option would be to override the template for the save page in your admin and add the needed code to the template. The needed media, Javascript, Css, etc, could be added using an inner Media class in your ModelAdmin class. This media class has two different attributes, a tuple with css stylesheets and a tuple with javascript files

I think for myself, that the best option in this case would be a custom address picker widget as you already mention in the your list of ways you don't want to do it.

Mark
+3  A: 

What is primarily being dealt with is client-side markup and client-side javascript. Being the case, it would seem that using a facility that's designed to handle those would be the proper choice. I'd also recommend making a custom admin widget. I've used this pattern myself. Depending on the size of the client-side markup, you can even make use of a Django template to render the widget.

As an alternative, you could write non-intrusive javascript to re-render that area of the page after the page has loaded. In this method, you could simply include that javascript media file with class Media: on the admin model.

This is more like pseudo-code than anything but it gives the idea:

admin.py

class AppointmentAdmin(admin.ModelAdmin):
    # ...

    class Media:
        from django.conf import settings
        media_url = getattr(settings, 'MEDIA_URL', '/media')
        js = [ media_url+'/admin/long-lat-render.js', ]

long-lat-render.js

// Written for jQuery
$(function(){
    // on page load...

    $('#_LongitudeTag').html('');

    var getCoordButton = $('<button id="get-coords"></button>');
    $('#_LongitudeTag').append(getCoordButton);

    addGMap($('#_LongitudeTag').get(0));
});

function addGMap(element) {
   // do whatevers
}
T. Stone