import os from django.conf import settings from django.forms import widgets from django.utils.safestring import mark_safe class LocationWidget(widgets.TextInput): """A widget that displays a map for selecting a location.""" def __init__( self, attrs=None, based_field=None, zoom=None, width=610, height=480, **kwargs ): self.based_field = based_field self.zoom = zoom self.width = width self.height = height super().__init__(attrs) def render(self, name, value, attrs=None, renderer=None): if value is not None and len(value) > 0: try: lat, lng, zoom = value.split(",") value = "%s,%s,%d" % (float(lat), float(lng), int(float(zoom))) except (ValueError, TypeError): value = "" else: value = "" if self.based_field is not None: based_field = "#id_" + self.based_field.name else: based_field = "" attrs = attrs or {} attrs["readonly"] = "readonly" attrs["data-location-widget"] = name attrs["data-based-field"] = based_field attrs["data-zoom"] = self.zoom or 7 attrs["data-map"] = "#map_" + name attrs["data-dialog-id"] = "#map_dialog_" + name text_input = super().render(name, value, attrs, renderer) # Load the HTML template for the map dialog path = os.path.abspath(os.path.dirname(__file__)) template_path = os.path.join(path, "media", "form.html") try: with open(template_path, "r") as content_file: html = content_file.read() html = html % {"name": name, "width": self.width, "height": self.height} except (FileNotFoundError, IOError): html = "" return mark_safe(text_input + html) @property def media(self): api_key = getattr(settings, "GOOGLE_MAPS_API_KEY", "") maps_url = f"https://maps.googleapis.com/maps/api/js?key={api_key}&language=de" return widgets.Media( css={"all": ("location_field/form.css",)}, js=( # jQuery and jQuery UI "https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js", "https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js", # Google Maps API with API key maps_url, "js/bindWithDelay.js", "location_field/form.js", ) )