passerelle-montpellier-sig/passerelle_montpellier_sig/views.py

270 lines
9.3 KiB
Python

import requests
import unicodedata
import pyproj
from django.views.generic.detail import SingleObjectMixin, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.base import View, RedirectView
from django.core.urlresolvers import reverse
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect
from passerelle import utils
from .models import MontpellierSig
from .forms import MontpellierSigForm
prefix_map = {
'ALL': 'ALLEE',
'AUTO': 'AUTOROUTE',
'AV': 'AVENUE',
'BASS': 'BASSIN',
'BD': 'BOULEVARD',
'CAR': 'CARREFOUR',
'CHE': 'CHEMIN',
'COUR': 'COUR',
'CRS': 'COURS',
'DESC': 'DESCENTE',
'DOM': 'DOMAINE',
'ENCL': 'ENCLOS',
'ESP': 'ESPLANADE',
'ESPA': 'ESPACE',
'GR': '', # "GR GRAND-RUE JEAN MOULIN"
'IMP': 'IMPASSE',
'JARD': 'JARDIN',
'MAIL': '', # "MAIL LE GRAND MAIL"
'PARC': 'PARC',
'PARV': '', # "PARV PARVIS DE LA LEGION D HONNEUR"
'PAS': 'PASSAGE',
'PL': 'PLACE',
'PLAN': 'PLAN',
'PONT': 'PONT',
'QUA': 'QUAI',
'R': 'RUE',
'RAMB': '', # "RAMB RAMBLA DES CALISSONS"
'RPT': 'ROND-POINT',
'RTE': 'ROUTE',
'SQ': 'SQUARE',
'TSSE': '', # "TSSE TERRASSE DES ALLEES DU BOIS"
'TUN': 'TUNNEL',
'VIAD': 'VIADUC',
'VOI': 'VOIE',
}
def prefix_cleanup(name):
name = name.strip()
for prefix, full in prefix_map.items():
if name.startswith(prefix + ' '):
name = (full + name[len(prefix):]).strip()
return name
def get_original_prefix(name):
name = name.strip()
for prefix, full in prefix_map.items():
if name.startswith(full + ' '):
name = (prefix + name[len(full):]).strip()
return name.upper()
def split_street(name):
name = name.strip()
for prefix, full in prefix_map.items():
prefix += ' '
if prefix in name:
index, name = name.split(prefix)
index = index.strip()
name = prefix_cleanup(prefix + name)
return index, name
class SigDetailView(DetailView):
model = MontpellierSig
COMMUNES = [
('34022', 'BAILLARGUES'),
('34027', 'BEAULIEU'),
('34057', 'CASTELNAU LE LEZ'),
('34058', 'CASTRIES'),
('34077', 'CLAPIERS'),
('34087', 'COURNONSEC'),
('34088', 'COURNONTERRAL'),
('34090', 'LE CRES'),
('34095', 'FABREGUES'),
('34116', 'GRABELS'),
('34120', 'JACOU'),
('34123', 'JUVIGNAC'),
('34129', 'LATTES'),
('34134', 'LAVERUNE'),
('34164', 'MONTAUD'),
('34169', 'MONTFERRIER-SUR-LEZ'),
('34172', 'MONTPELLIER'),
('34179', 'MURVIEL-LES-MONTPELLIER'),
('34198', 'PEROLS'),
('34202', 'PIGNAN'),
('34217', 'PRADES-LE-LEZ'),
('34227', 'RESTINCLIERES'),
('34244', 'SAINT-BRES'),
('34249', 'SAINT-DREZERY'),
('34256', 'SAINT-GENIES-DES-MOURGUES'),
('34259', 'SAINT GEORGES D ORQUES'),
('34270', 'SAINT-JEAN-DE-VEDAS'),
('34295', 'SAUSSAN'),
('34307', 'SUSSARGUES'),
('34327', 'VENDARGUES'),
('34337', 'VILLENEUVE-LES-MAGUELONE'),
]
class CommunesView(View, SingleObjectMixin):
model = MontpellierSig
def get(self, request, *args, **kwargs):
communes = COMMUNES
if 'q' in request.GET:
communes = [x for x in communes if request.GET['q'].upper() in x[1]]
communes = [{'id': x[0], 'text': x[1]} for x in communes]
return utils.response_for_json(request, {'data': communes})
class VoiesView(View, SingleObjectMixin):
model = MontpellierSig
def get(self, request, *args, **kwargs):
insee = kwargs['insee']
result = self.get_object().sig_request('commune/' + insee + '/voie')
voies = []
if isinstance(result, dict) and result.get('error'):
return utils.response_for_json(request, {'data': voies})
for i in result:
voie = i['attributes']['nom_voie']
voies.append({'id': voie, 'text': prefix_cleanup(voie)})
if 'q' in request.GET and request.GET['q']:
q = request.GET['q'].upper()
q = q.replace("'", ' ')
q = unicodedata.normalize('NFKD', q).encode('ascii', 'ignore')
voies = [v for v in voies if q in v['text']]
voies.sort(lambda x, y: cmp(x['id'], y['id']))
return utils.response_for_json(request, {'data': voies})
class VoiesCommuneView(View, SingleObjectMixin):
"""
Called service
$ curl .../adresse/rest/commune/34057/voie/ALL DES CONDAMINES/numero
Expected result when called with no street number:
[{"attributes": {"nom_voie": "ALL DES CONDAMINES", "numero": 8}, ...]
When called with street number:
$ curl .../adresse/rest/commune/34057/voie/ALL DES CONDAMINES/numero/8
Expected result:
[{"geometry": {"y": 6281724.800000001, "x": 773304.5},
"attributes": {"numero": 8, "nom_voie": "ALL DES CONDAMINES"}},
...]
"""
model = MontpellierSig
def get(self, request, *args, **kwargs):
insee = kwargs['insee']
nom_rue = get_original_prefix(kwargs['nom_rue'])
if 'q' in request.GET:
result = self.get_object().sig_request('commune/' + insee + '/voie/' + nom_rue + '/numero/' + request.GET['q'])
else:
result = self.get_object().sig_request('commune/' + insee + '/voie/' + nom_rue + '/numero')
voies_communes = []
if isinstance(result, dict) and result.get('error'):
return utils.response_for_json(request, {'data': voies_communes})
for i in result:
attrs = i['attributes']
voie = {'id': '%(numero)s %(nom_voie)s' % attrs,
'text': '%(numero)s %(nom_voie)s' % attrs}
if i.get('geometry'):
voie.update({'x': i['geometry'].get('x'), 'y': i['geometry'].get('y')})
voies_communes.append(voie)
voies_communes.sort(lambda x, y: cmp(x['id'], y['id']))
return utils.response_for_json(request, {'data': voies_communes})
class VoieCommuneView(View, SingleObjectMixin):
model = MontpellierSig
def get(self, request, *args, **kwargs):
result = self.get_object().sig_request('voiecommune/' + kwargs['nom_rue'])
voies_communes = []
if isinstance(result, dict) and result.get('error'):
return utils.response_for_json(request, {'data': voies_communes})
for i in result:
attrs = i['attributes']
voies_communes.append({'id': '%(nom_voie)s' % attrs,
'text': '%(nom_voie)s' % attrs,
'commune': attrs['commune'],
'insee': attrs['code_insee']
})
voies_communes.sort(lambda x, y: cmp(x['insee'], y['insee']))
return utils.response_for_json(request, {'data': voies_communes})
class AdresseView(View, SingleObjectMixin):
model = MontpellierSig
def get(self, request, *args, **kwargs):
lat = request.GET.get('lat')
lon = request.GET.get('lon')
# WGS84: epsg:4326
wgs84 = pyproj.Proj(init='epsg:4326')
# Lambert93: epsg:2154
lambert93 = pyproj.Proj(init='epsg:2154')
try:
l_lon, l_lat = pyproj.transform(wgs84, lambert93, lon, lat)
except TypeError:
return HttpResponseBadRequest()
result = self.get_object().sig_request('adresse/%s/%s' %(l_lon, l_lat))
house_number, road = split_street(result.get('voie'))
address = {'road': road,
'house_number': house_number,
'city': result.get('commune'),
'neighbourhood': result.get('sousquartier'),
'postcode': result.get('codepostal'),
'suburb': result.get('quartier'),
'country': 'France',
}
return utils.response_for_json(request, {'address': address})
class DistrictView(View, SingleObjectMixin):
model = MontpellierSig
def get(self, request, *args, **kwargs):
insee = kwargs['insee']
nom_rue = get_original_prefix(kwargs['nom_rue'])
numero = kwargs['numero']
uri = 'commune/%s/voie/%s/numero/%s' % (insee, nom_rue, numero)
result = self.get_object().sig_request(uri)
if isinstance(result, dict) and result.get('error'):
return utils.response_for_json(request, {'data': []})
if result:
r = result[0]
data = self.get_object().sig_request('adresse/%s/%s' %(r['geometry'].get('x'), r['geometry'].get('y')))
return utils.response_for_json(request, {'data': data})
return utils.response_for_json(request, {'data': []})
class ViewerUrlView(View, SingleObjectMixin):
model = MontpellierSig
permanent = False
def get(self, request, *args, **kwargs):
lat = request.GET.get('lat')
lon = request.GET.get('lon')
# WGS84: epsg:4326
wgs84 = pyproj.Proj(init='epsg:4326')
# Lambert93: epsg:2154
lambert93 = pyproj.Proj(init='epsg:2154')
try:
l_lon, l_lat = pyproj.transform(wgs84, lambert93, lon, lat)
except TypeError:
return HttpResponseBadRequest()
area = l_lon-50, l_lat-50, l_lon+50, l_lat+50
return redirect('http://sig.montpellier-agglo.com/WebVilleServer/resources/index.html#extent:%s;%s;%s;%s' % area)