You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
7.1 KiB
215 lines
7.1 KiB
# -*- coding: utf-8 -*-
|
|
from django.db import models
|
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
from django import forms
|
|
from django.utils.safestring import mark_safe
|
|
from django.conf import settings
|
|
try:
|
|
import json
|
|
except:
|
|
from django.utils import simplejson as json
|
|
|
|
|
|
FILE_TYPES = ('PDF', 'DOC', 'TXT', 'OTHER')
|
|
IMG_TYPES = ('JPG', 'BMP', 'PNG', 'GIF',)
|
|
|
|
PURPOSES = ('photo', 'flat')
|
|
|
|
|
|
class EnumField(models.Field):
|
|
"""
|
|
A field class that maps to MySQL's ENUM type.
|
|
Usage:
|
|
Class Card(models.Model):
|
|
suit = EnumField(values=('Clubs', 'Diamonds', 'Spades', 'Hearts'))
|
|
|
|
c = Card()
|
|
c.suit = 'Clubs'
|
|
c.save()
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
self.values = kwargs.pop('values')
|
|
kwargs['choices'] = [(v, v) for v in self.values]
|
|
kwargs['default'] = self.values[0]
|
|
super(EnumField, self).__init__(*args, **kwargs)
|
|
|
|
def db_type(self, connection):
|
|
return "enum({0})".format( ','.join("'%s'" % v for v in self.values) )
|
|
|
|
|
|
#snippet http://djangosnippets.org/snippets/1478/
|
|
class JSONField(models.TextField):
|
|
"""JSONField is a generic textfield that neatly serializes/unserializes
|
|
JSON objects seamlessly"""
|
|
|
|
# Used so to_python() is called
|
|
__metaclass__ = models.SubfieldBase
|
|
|
|
def to_python(self, value):
|
|
"""Convert our string value to JSON after we load it from the DB"""
|
|
|
|
if value == "":
|
|
return None
|
|
|
|
try:
|
|
if isinstance(value, basestring):
|
|
return json.loads(value)
|
|
except ValueError:
|
|
pass
|
|
|
|
return value
|
|
|
|
def get_db_prep_save(self, value, connection):
|
|
"""Convert our JSON object to a string before we save"""
|
|
|
|
if value == "":
|
|
return None
|
|
|
|
if isinstance(value, dict):
|
|
value = json.dumps(value, cls=DjangoJSONEncoder)
|
|
|
|
return value
|
|
|
|
|
|
|
|
DEFAULT_WIDTH = 590
|
|
DEFAULT_HEIGHT = 200
|
|
|
|
DEFAULT_LAT = 55.75
|
|
DEFAULT_LNG = 37.62
|
|
DEFAULT_ADDRESS = u'(Не задано)'
|
|
|
|
class LocationWidget(forms.TextInput):
|
|
def __init__(self, *args, **kw):
|
|
self.map_width = kw.get("map_width", DEFAULT_WIDTH)
|
|
self.map_height = kw.get("map_height", DEFAULT_HEIGHT)
|
|
|
|
super(LocationWidget, self).__init__(*args, **kw)
|
|
self.inner_widget = forms.widgets.HiddenInput()
|
|
|
|
def render(self, name, value, *args, **kwargs):
|
|
"""
|
|
handle on the rendering on the server
|
|
"""
|
|
if value is None:
|
|
lat, lng, address = DEFAULT_LAT, DEFAULT_LNG, DEFAULT_ADDRESS
|
|
value = {'lat': lat, 'lng': lng, 'address': address}
|
|
else:
|
|
try:
|
|
lat, lng, address = float(value['lat']), float(value['lng']), value['address']
|
|
except:
|
|
a = json.loads(value)
|
|
lat, lng, address = float(a['lat']), float(a['lng']), a['address']
|
|
|
|
|
|
curLocation = json.dumps(value, cls=DjangoJSONEncoder)
|
|
|
|
js = '''
|
|
<script type="text/javascript">
|
|
//<![CDATA[
|
|
var map_%(functionName)s;
|
|
|
|
function savePosition_%(functionName)s(point, address)
|
|
{
|
|
var input = document.getElementById("id_%(name)s");
|
|
var location = {'lat': point.lat().toFixed(6), 'lng': point.lng().toFixed(6)};
|
|
location.address = '%(defAddress)s';
|
|
if (address) {
|
|
location.address = address;
|
|
}
|
|
input.value = JSON.stringify(location);
|
|
map_%(functionName)s.panTo(point);
|
|
}
|
|
|
|
function load_%(functionName)s() {
|
|
var point = new google.maps.LatLng(%(lat)f, %(lng)f);
|
|
|
|
var options = {
|
|
zoom: 13,
|
|
center: point,
|
|
mapTypeId: google.maps.MapTypeId.ROADMAP
|
|
};
|
|
|
|
map_%(functionName)s = new google.maps.Map(document.getElementById("map_%(name)s"), options);
|
|
|
|
geocoder = new google.maps.Geocoder();
|
|
|
|
var marker = new google.maps.Marker({
|
|
map: map_%(functionName)s,
|
|
position: point,
|
|
draggable: true
|
|
});
|
|
|
|
google.maps.event.addListener(marker, 'dragend', function(mouseEvent) {
|
|
geocoder.geocode({'latLng': mouseEvent.latLng}, function(results, status) {
|
|
if (status == google.maps.GeocoderStatus.OK && results[0]) {
|
|
$('#address_%(name)s').val(results[0].formatted_address);
|
|
savePosition_%(functionName)s(mouseEvent.latLng, results[0].formatted_address);
|
|
}
|
|
else {
|
|
savePosition_%(functionName)s(mouseEvent.latLng);
|
|
}
|
|
});
|
|
});
|
|
|
|
google.maps.event.addListener(map_%(functionName)s, 'click', function(mouseEvent){
|
|
marker.setPosition(mouseEvent.latLng);
|
|
geocoder.geocode({'latLng': mouseEvent.latLng}, function(results, status) {
|
|
if (status == google.maps.GeocoderStatus.OK && results[0]) {
|
|
$('#address_%(name)s').val(results[0].formatted_address);
|
|
savePosition_%(functionName)s(mouseEvent.latLng, results[0].formatted_address);
|
|
}
|
|
else {
|
|
savePosition_%(functionName)s(mouseEvent.latLng);
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#address_%(name)s').autocomplete({
|
|
source: function(request, response) {
|
|
geocoder.geocode({'address': request.term}, function(results, status) {
|
|
response($.map(results, function(item) {
|
|
return {
|
|
value: item.formatted_address,
|
|
location: item.geometry.location
|
|
}
|
|
}));
|
|
})
|
|
},
|
|
select: function(event, ui) {
|
|
marker.setPosition(ui.item.location);
|
|
savePosition_%(functionName)s(ui.item.location, ui.item.value);
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).ready(function(){
|
|
load_%(functionName)s();
|
|
});
|
|
|
|
//]]>
|
|
</script>
|
|
''' % dict(functionName=name.replace('-', '_'), name=name, lat=lat, lng=lng, defAddress=DEFAULT_ADDRESS)
|
|
html = self.inner_widget.render("%s" % name, "%s" % curLocation, dict(id='id_%s' % name))
|
|
html += '<input style="width: 580px" id="address_%s" type="text"/><br>' % ( name)
|
|
html += '<br/><div id="map_%s" style="width: %dpx; height: %dpx"></div>' % (name, self.map_width, self.map_height)
|
|
|
|
html += '<br /><label>%s: </label><span>%s</span>' % (u'Текущий адрес', address)
|
|
|
|
return mark_safe(js + html)
|
|
|
|
class Media:
|
|
css = {'all': (
|
|
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/redmond/jquery-ui.css',
|
|
settings.MEDIA_URL+'css/main.css',
|
|
)}
|
|
js = (
|
|
'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
|
|
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js',
|
|
'http://maps.google.com/maps/api/js?sensor=false',
|
|
)
|
|
|
|
class LocationField(JSONField):
|
|
def formfield(self, **kwargs):
|
|
defaults = {'widget': LocationWidget}
|
|
return super(LocationField, self).formfield(**defaults)
|
|
|