Metadata-Version: 2.4
Name: django-osm-widgets
Version: 0.2.2
Summary: Improved widgets for Django's PointField
License: BSD-3-Clause
License-File: LICENSE
Author: Kapt
Author-email: dev@kapt.mobi
Requires-Python: >=3.10
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: Django (>=3.0,<5.2)
Project-URL: Repository, https://gitlab.com/kapt/open-source/django-osm-widgets
Description-Content-Type: text/markdown

# django-osm-widgets

Improved widgets for Django's PointField.

`LatLonOpenlayersOSMWidget` handles latitude and longitude inputs synced with the point on the map.


![Example of the LatLonOpenlayersOSMWidget on a page](https://gitlab.com/kapt/open-source/django-osm-widgets/-/raw/main/preview.jpg)

# Requirements

- Python 3.10+
- Django >=3.0, <5.2

# Installation

- run `pip install django-osm-widgets`
- add `django_osm_widgets` to your `INSTALLED_APPS`

# Usage

In your forms, use the widget like this:

```py
from django.contrib.gis.forms.fields import PointField
from django_osm_widgets.widgets import LatLonOpenlayersOSMWidget


class MyForm(forms.Form):
  location = PointField(widget=LatLonOpenlayersOSMWidget)
```

The latitute and longitude fields will be automatically added in your page.

Currently `django-osm-widgets` supports only a unique instance of the `LatLonOpenlayersOSMWidget` in a page.

# Customizations

You can define some options as in the example below.

When using `"must_display_latlon_fields": False,` your are responsible for providing two input fields in your page. These fields must have ids corresponding to `latitude_field_id` and `longitude_field_id` values (defaults to `id_osm_widget_latitude` and `id_osm_widget_longitude`) and must appear in the DOM before the LatLonOpenlayersOSMWidget.```

When using `"must_display_geocoder_button": False,` you are responsible for providing a button with an id corresponding to `geocoder_button_id` value (defaults to `id_geocoder_button`).

You can override some attributes when instantiating the widget class in your form. Below are all the attributes and their default values.

```py
from django.contrib.gis.forms.fields import PointField
from django_osm_widgets.widgets import LatLonOpenlayersOSMWidget


class MyForm(forms.Form):
  location = PointField(
    widget=LatLonOpenlayersOSMWidget(
      attrs={
        "must_display_latlon_fields": True,
        "must_display_geocoder_button": True,
        "map_width": "auto",
        "map_height": "auto",
        "default_lat": 45,
        "default_lon": 5,
        "default_zoom": 8,
        "latitude_field_id": "id_osm_widget_latitude",
        "longitude_field_id": "id_osm_widget_longitude",
        "listened_events": "input",
        "marker_options": {
          "src": "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/images/marker-icon.png",
          "scale": 1,
          "anchor": [0.5, 1],
        },
        "precision": 4,
        "geocoder_address_field_ids": ["id_adresse", "id_code_postal", "id_localite", "id_pays"],
        "geocoder_provider": "nominatim",
        "geocoder_button_id": "id_geocoder_button",
        "geocoder_message_container_id": "id_geocoder_message",
        "clear_features_label": "Delete all Features",
        "geocoder_button_label": "Geolocate from address",
        "geocoder_message_timeout": 5000,
      }
    )
  )
```

Projects can override button labels and the status message timeout:

- **Via widget attrs**: Pass `clear_features_label`, `geocoder_button_label`, `geocoder_message_timeout` when instantiating the widget.
- **Via template blocks**: Extend `latlon-openlayers-osm.html` and override `{% block clear_features_label %}` or `{% block geocoder_button_label %}` for full control.

Labels support translation when using Django's i18n. The status message (e.g. "Coordinates updated.") disappears automatically after `geocoder_message_timeout` milliseconds (default 5 seconds).

# Geocoding from address

When `geocoder_address_field_ids` is provided, a "Geocode from address" button appears next to the map. When clicked, the widget fetches coordinates of the address formed by concatenating values of the `geocoder_address_fields_ids` (keeping the order) and updates the map.

The geocoding provider is configurable via `geocoder_provider`:

- **`nominatim`** (default): [OpenStreetMap Nominatim](https://nominatim.openstreetmap.org/). Works worldwide with international addresses.
- **`ign`**: [IGN Géoplateforme](https://geoservices.ign.fr/documentation/services/services-geoplateforme/geocodage). Optimized for French addresses (BAN, BD TOPO®, Parcellaire Express). 50 requests/second limit per IP.

Example for French addresses:

```py
"geocoder_provider": "ign",
```

You can omit any of the four address keys; at least one address field must be filled.

