passerelle-montpellier-sig/passerelle_montpellier_sig/views.py

293 lines
9.5 KiB
Python

import unicodedata
import pyproj
import requests
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect
from django.utils.encoding import force_text
from django.views.generic.base import RedirectView, View
from django.views.generic.detail import DetailView, SingleObjectMixin
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from passerelle import utils
from .forms import MontpellierSigForm
from .models import MontpellierSig
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):
if not name:
return ''
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):
if not name:
return ''
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):
if not name:
return '', ''
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']
if 'id' in request.GET and voie != request.GET['id']:
continue
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')
q = force_text(q)
voies = [v for v in voies if q in v['text']]
voies.sort(key=lambda x: x['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(key=lambda x: x['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(key=lambda x: x['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
)