Skip to content

Instantly share code, notes, and snippets.

@armonge
Created July 18, 2011 14:41
Show Gist options
  • Save armonge/1089705 to your computer and use it in GitHub Desktop.
Save armonge/1089705 to your computer and use it in GitHub Desktop.
A Django custom modelfield, formfield and formwidget to select and save a set of geographic coordinates using Google Maps
class GoogleMapMarker(object):
def __init__(self, latitude, longitude):
self.latitude = latitude
self.longitude = longitude
def __unicode__(self):
return '%f,%f'%(self.latitude, self.longitude)
def __len__(self):
return len(self.__unicode__())
class GoogleMapMarkerField(models.Field):
__metaclass__ = models.SubfieldBase
description = _('Un marcador de Google Maps')
def __init__(self,center, widget = None,*args, **kwargs):
kwargs['max_length'] = 100
kwargs['help_text']=_('Arrastre el cursor en el mapa para seleccionar el punto')
self.center =center
super(GoogleMapMarkerField, self).__init__(*args,**kwargs)
def get_internal_type(self):
return "CharField"
def formfield(self,**kwargs):
defaults = {
'center':self.center,
}
defaults.update(kwargs)
return super(GoogleMapMarkerField, self).formfield( form_class = GoogleMapMarkerFormField, **kwargs)
def to_python(self, value):
if isinstance(value,GoogleMapMarker):
return value
if isinstance(value, list):
return GoogleMapMarker(*map(float,value))
elif isinstance(value, basestring):
try:
return GoogleMapMarker(*map(float, value.split(',')))
except ValueError:
pass
def get_prep_value(self, value):
return '%f,%f'%(value.latitude,value.longitude)
class GoogleMapMarkerWidget(forms.MultiWidget):
def __init__(self, attrs=None, **kwargs):
widgets = (
forms.TextInput(attrs),
forms.TextInput(attrs),
)
super(GoogleMapMarkerWidget, self).__init__(widgets, attrs, **kwargs)
def decompress(self, value):
return [value.latitude, value.longitude]
def render(self, name, value, attrs=None):
if value is not None:
if isinstance(value, basestring):
lat, lng = map(float, value.split(',') )
value = [lat, lng]
else:
value= [None, None]
html = super(GoogleMapMarkerWidget, self).render(name, value, attrs)
html += u'''
<div class="map" id="map-%(id)s"></div>
<script type="text/javascript">
loadMap("map-%(id)s");
</script>
'''%{'id':attrs['id']}
return mark_safe(html)
class Media:
js = (
'http://maps.google.com/maps/api/js?sensor=true',
'js/gmapmarker-admin.js',
)
css = {
'screen':('css/map-field.css',)
}
class GoogleMapMarkerFormField(forms.MultiValueField):
def __init__(self,widget = None, **kwargs):
fields=(
forms.FloatField(label = _('Latitud')),
forms.FloatField(label=_('Longitud'))
)
if widget is None:
widget = GoogleMapMarkerWidget()
super(GoogleMapMarkerFormField,self).__init__(widget=widget,fields=fields,**kwargs)
def compress(self, data_list):
if data_list:
return data_list
return [None, None]
from south.modelsinspector import add_introspection_rules
add_introspection_rules([
(
[GoogleMapMarkerField], # Class(es) these apply to$
[], # Positional arguments (not used)$
{ # Keyword argument$
"center": ["center", {}],
},
),
], ["^core\.fields\.GoogleMapMarkerField"])
/**
* Created by PyCharm.
* User: armonge
* Date: 11/07/11
* Time: 11:49
*/
function loadMap(mapHolder){
$ = django.jQuery;
$mapHolder = $('#'+mapHolder)
mapHolder = document.getElementById(mapHolder)
var defaultLat = 12.865416;
var defaultLng = -85.207229;
var $latInput = $mapHolder.closest('.map_marker').find('input:first');
var $longInput = $mapHolder.closest('.map_marker').find('input:last');
var latLong = new google.maps.LatLng(defaultLat, defaultLng );
var mapOptions = {
zoom:6,
mapTypeId:google.maps.MapTypeId.ROADMAP,
center: latLong
}
var map = new google.maps.Map(mapHolder, mapOptions);
var markerLat = parseFloat( $latInput.val());
var markerLong = parseFloat( $longInput.val());
if(isNaN(markerLat )){
markerLat = defaultLat
}
if(isNaN(markerLong)){
markerLong = defaultLng
}
var markerPosition = new google.maps.LatLng(markerLat, markerLong);
var marker = new google.maps.Marker({
position:markerPosition,
map:map,
title:'Posición',
draggable:true
})
google.maps.event.addListener(marker,'dragend',function(event){
$latInput.val(event.latLng.lat());
$longInput.val(event.latLng.lng());
});
}
.map{
width:500px;
height: 300px;
margin: 0 auto;
border: 1px solid #eee;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment