parent
27ceac1e46
commit
91907be984
@ -16,6 +16,7 @@ from django.forms import (
|
||||
)
|
||||
from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget
|
||||
|
||||
from .utils import PlaceGuesser
|
||||
from .models import (
|
||||
Event,
|
||||
RecurrentImport,
|
||||
@ -741,13 +742,17 @@ class PlaceForm(ModelForm):
|
||||
fields = "__all__"
|
||||
widgets = {"location": TextInput()}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.force_adjust = kwargs.pop("force_adjust", None)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def as_grid(self):
|
||||
return mark_safe(
|
||||
'<div class="grid"><div>'
|
||||
result = ('<div class="grid"><div>'
|
||||
+ super().as_p()
|
||||
+ '</div><div><div class="map-widget">'
|
||||
+ '<div id="map_location" style="width: 100%; aspect-ratio: 16/9"></div><p>Cliquez pour ajuster la position GPS</p></div></div></div>'
|
||||
)
|
||||
+ '<div id="map_location" style="width: 100%; aspect-ratio: 16/9"></div><p>Cliquez pour ajuster la position GPS</p></div></div></div>')
|
||||
|
||||
return mark_safe(result)
|
||||
|
||||
def apply(self):
|
||||
return self.cleaned_data.get("apply_to_all")
|
||||
|
@ -22,6 +22,7 @@
|
||||
<article>
|
||||
{% if event %}
|
||||
<p>Création d'un lieu depuis l'événement « {{ event }} » (voir en bas de page le détail de l'événement).</p>
|
||||
<p><strong>Remarque :</strong> les champs ont été pré-remplis à partir de la description sous forme libre et n'est probablement pas parfaite.</p>
|
||||
{% endif %}
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_grid }}
|
||||
|
114
src/agenda_culturel/utils.py
Normal file
114
src/agenda_culturel/utils.py
Normal file
@ -0,0 +1,114 @@
|
||||
from agenda_culturel.models import ReferenceLocation
|
||||
import re
|
||||
import unicodedata
|
||||
|
||||
|
||||
class PlaceGuesser:
|
||||
|
||||
def __init__(self):
|
||||
self.__citynames = list(ReferenceLocation.objects.values_list("name__lower__unaccent", "name")) + [("clermont-fd", "Clermont-Ferrand"), ("aurillac", "Aurillac"), ("montlucon", "Montluçon"), ("montferrand", "Clermont-Ferrand")]
|
||||
self.__citynames = [(x[0].replace("-", " "), x[1]) for x in self.__citynames]
|
||||
|
||||
def __remove_accents(self, input_str):
|
||||
if input_str is None:
|
||||
return None
|
||||
nfkd_form = unicodedata.normalize("NFKD", input_str)
|
||||
return "".join([c for c in nfkd_form if not unicodedata.combining(c)])
|
||||
|
||||
|
||||
def __guess_is_address(self, part):
|
||||
toponyms = ["bd", "rue", "avenue", "place", "boulevard", "allee", ]
|
||||
part = part.strip()
|
||||
if re.match(r'^[0-9]', part):
|
||||
return True
|
||||
|
||||
elems = part.split(" ")
|
||||
return any([self.__remove_accents(e.lower()) in toponyms for e in elems])
|
||||
|
||||
|
||||
def __clean_address(self, addr):
|
||||
toponyms = ["bd", "rue", "avenue", "place", "boulevard", "allée", "bis", "ter", "ZI"]
|
||||
for t in toponyms:
|
||||
addr = re.sub(" " + t + " ", " " + t + " ", addr, flags=re.IGNORECASE)
|
||||
return addr
|
||||
|
||||
def __guess_city_name(self, part):
|
||||
part = part.strip().replace(" - ", "-")
|
||||
if len(part) == 0:
|
||||
return None
|
||||
part = self.__remove_accents(part.lower()).replace("-", " ")
|
||||
match = [x[1] for x in self.__citynames if x[0] == part]
|
||||
if len(match) > 0:
|
||||
return match[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __guess_city_name_postcode(self, part):
|
||||
with_pc = re.search(r'^(.*)(([0-9][ ]*){5})(.*)$', part)
|
||||
if with_pc:
|
||||
p1 = self.__guess_city_name(with_pc.group(1).strip())
|
||||
postcode = with_pc.group(2).replace(" ", "")
|
||||
p2 = self.__guess_city_name(with_pc.group(4).strip())
|
||||
return postcode, p2, p1
|
||||
else:
|
||||
return None, self.__guess_city_name(part), None
|
||||
|
||||
def __guess_name_address(self, part):
|
||||
with_num = re.search(r'^(([^0-9])+)([0-9]+)(.*)', part)
|
||||
if with_num:
|
||||
name = with_num.group(1)
|
||||
return name, part[len(name):]
|
||||
else:
|
||||
return "", part
|
||||
|
||||
def guess_address_elements(self, alias):
|
||||
parts = re.split(r'[,/à]', alias)
|
||||
parts = [p1 for p1 in [p.strip() for p in parts] if p1 != "" and p1.lower() != "france"]
|
||||
|
||||
name = ""
|
||||
address = ""
|
||||
postcode = ""
|
||||
city = ""
|
||||
possible_city = ""
|
||||
|
||||
oparts = []
|
||||
for part in parts:
|
||||
p, c, possible_c = self.__guess_city_name_postcode(part)
|
||||
if not possible_c is None:
|
||||
possible_city = possible_c
|
||||
if not c is None and city == "":
|
||||
city = c
|
||||
if not p is None and postcode == "":
|
||||
postcode = p
|
||||
if p is None and c is None:
|
||||
oparts.append(part)
|
||||
|
||||
if city == "" and possible_city != "":
|
||||
city = possible_city
|
||||
else:
|
||||
if len(oparts) == 0 and not possible_city != "":
|
||||
oparts = [possible_city]
|
||||
|
||||
if city == "":
|
||||
alias_simple = self.__remove_accents(alias.lower()).replace("-", " ")
|
||||
mc = [x[1] for x in self.__citynames if alias_simple.endswith(" " + x[0])]
|
||||
if len(mc) == 1:
|
||||
city = mc[0]
|
||||
|
||||
|
||||
|
||||
|
||||
if len(oparts) > 0:
|
||||
if not self.__guess_is_address(oparts[0]):
|
||||
name = oparts[0]
|
||||
address = ", ".join(oparts[1:])
|
||||
else:
|
||||
name, address = self.__guess_name_address(", ".join(oparts))
|
||||
|
||||
address = self.__clean_address(address)
|
||||
|
||||
if name == "" and possible_city != "" and possible_city != city:
|
||||
name = possible_city
|
||||
|
||||
return name, address, postcode, city
|
||||
|
@ -12,6 +12,7 @@ from django.contrib.postgres.search import SearchQuery, SearchHeadline
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.decorators import method_decorator
|
||||
from honeypot.decorators import check_honeypot
|
||||
from .utils import PlaceGuesser
|
||||
|
||||
|
||||
from django.contrib.gis.geos import Point
|
||||
@ -1864,16 +1865,30 @@ class UnknownPlaceAddView(PermissionRequiredMixin, SuccessMessageMixin, UpdateVi
|
||||
|
||||
|
||||
class PlaceFromEventCreateView(PlaceCreateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["event"] = self.event
|
||||
return context
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
if self.event.location and "add" in self.request.GET:
|
||||
kwargs["force_adjust"] = True
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_initial(self, *args, **kwargs):
|
||||
initial = super().get_initial(**kwargs)
|
||||
self.event = get_object_or_404(Event, pk=self.kwargs["pk"])
|
||||
if self.event.location and "add" in self.request.GET:
|
||||
initial["aliases"] = [self.event.location]
|
||||
guesser = PlaceGuesser()
|
||||
name, address, postcode, city = guesser.guess_address_elements(self.event.location)
|
||||
initial["name"] = name
|
||||
initial["address"] = address
|
||||
initial["city"] = city
|
||||
|
||||
return initial
|
||||
|
||||
def form_valid(self, form):
|
||||
|
Loading…
Reference in New Issue
Block a user