Des cartes avec GeoDjango et Leaflet

Un guide pas à pas pour visualiser vos modèles Django avec Leaflet

Le blog Makina-corpus

Un guide pas à pas pour visualiser vos modèles Django avec Leaflet

Une brève introduction au Web mapping avec Django, en utilisant deux applications développées par Makina Corpus: django-leaflet et django-geojson.

Nous allons construire une carte avec les stations métérologiques du monde.


Une station météo

Chaque station a un identifiant, un nom et une position.

En GeoDjango, le modèle donne ça :

# models.py from django.db import models from django.contrib.gis.db import models as gismodels

class WeatherStation(gismodels.Model):

wmoid = models.IntegerField(primary_key=True) name = models.CharField(max_length=256)

geom = gismodels.PointField()

objects = gismodels.GeoManager()

def __unicode(self): return self.name

Charger des données réelles

L'Organisation Mondiale de la Météorologie publie une liste de toutes les stations météo du monde, au format CSV.

Malheureusement, le format n'est pas très pratique (les latitudes et longitudes en particulier) :

StationId   StationName         Latitude    Longitude ...
60351       JIJEL- ACHOUAT      36 48 00N   05 53 00E
...
07630       TOULOUSE BLAGNAC    43 37 16N   01 22 44E
...

Nous allons convertir les coordonnées en degrés minutes secondes vers des degrés décimaux:

def dms2dec(value): """ Degres Minutes Seconds to Decimal degres """ degres, minutes, seconds = value.split() seconds, direction = seconds[:-1], seconds[-1] dec = float(degres) + float(minutes)/60 + float(seconds)/3600 if direction in ('S', 'W'): return -dec return dec

Pour ensuite créer une instance de notre modèle pour chaque ligne du fichier CSV :

import csv from django.contrib.gis.geos import Point

from webmap.models import WeatherStation

csv_file = 'Pub9volA130819x.flatfile.txt'

reader = csv.DictReader(open(csv_file, 'rb'), delimiter="\t") for line in reader: lng = dms2dec(line.pop('Longitude')) lat = dms2dec(line.pop('Latitude')) wmoid = int(line.pop('StationId')) name = line.pop('StationName').title()

WeatherStation(wmoid=wmoid, name=name, geom=Point(lng, lat)).save()

Ça y est, notre table est remplie (  12000 enregistrements) !

Si on l'ouvre avec un outil graphique, comme QGIS, c'est touffu !

( Si vous voulez un script qui convertit le CSV des stations vers un simple GeoJSON, vous pouvez utiliser ce morceau de code)


Visualiser sur la carte

Avec django-leaflet, après avoir ajouté leaflet au setting INSTALLED_APPS, vous pouvez ajouter des cartes dans les templates :

{% load leaflet_tags %} <html> <head> {% leaflet_js %} {% leaflet_css %} </head> <body> <h1>Weather Stations</h1> {% leaflet_map "main" callback="main_map_init" %}

<script type="text/javascript"> function main_map_init (map, options) { // Use Leaflet API here } </script> body>

</html>

Une carte vide s'affiche, avec un fond basique OpenStreetMap.

Données vectorielles

Nous souhaitons maintenant placer des marqueurs à l'emplacement de chaque station météo. Pour ça, nous utilisons django-geojson, qui fournit une vue de base très simple :

# urls.py

from djgeojson.views import GeoJSONLayerView

from webmap.models import WeatherStation

urlpatterns = patterns('', url(r'^data.geojson$', GeoJSONLayerView.as_view(model=WeatherStation), name='data') )

Les données sont ensuite chargées en Ajax, et ajoutées en tant que couche sur la carte, et ce dans la fonction d'initialisation que nous avions laissée vide à l'extrait précédent :

function main_map_init (map, options) {

var dataurl = '{% url "data" %}'; // Download GeoJSON via Ajax $.getJSON(dataurl, function (data) { // Add GeoJSON layer L.geoJson(data).addTo(map); });

}

La carte s'affiche, et se remplit avec les stations !


Aller plus loin...

Il s'agit d'une introduction, mais cela s'applique à tous les types de géometries (lignes, polygones, ...)

J'ai publié le project complet si vous voulez partir d'un exemple concret.

Mais si vous êtes à l'aise en Django, il n'y aura pas de surprise : jetez un oeil aux documentations de Leaflet, django-leaflet and django-geojson pour avoir une idée des possibilités offertes...

Performance

Une carte avec plus de 12 000 objets HTML ne sera pas réactive.

Il y a peu de chances ceci dit, que ce soit le cas de votre première application !

Et de toutes façons, heureusement, il y a énormément de stratégies différentes pour visualiser une telle quantité de données :

  • Utiliser des clusters pour réduire le nombre d'éléments dans la carte (voir résultat ici) ;
  • Dessiner des cercles au lieu des marqueurs et passer aux Canvas (voir la documentation de Leaflet) ;
  • Utiliser des geojson tuilés ;
  • Faire le rendu de tuiles avec Tilemill/Mapnik ;
  • ...

Cela nous ouvre des pistes à explorer et de quoi alimenter le blog :)

Actualités en lien

Image
Vidéo conférence SIG Webmapping Frédéric Rodrigo
23/11/2021

Vidéo conférence : Makina Maps, un serveur de fond de carte vectorielle basé sur OpenStreetMap

Visionnez la vidéo de la conférence de Frédéric RODRIGO, expert OpenStreetMap Makina Corpus, à l'Open Source Expérience 2021 : Makina Maps, un serveur de fond de carte vectorielle basé sur OpenStreetMap.

Voir l'article
Image
OppServe_Martinique_comparaison.png
23/11/2021

OppServe, gérez l'Observatoire Photographique des Paysages de votre territoire !

Découvrez OppServe pour intégrer vos photos, influencer les politiques d’aménagement et sensibiliser le public

 

Voir l'article
Image
Django Python Keycloak
18/11/2021

Administrer des comptes Keycloak depuis une application Python/Django

Dans cet article, nous allons créer une application Python/Django qui agira en tant que maître sur Keycloak afin de pouvoir ajouter facilement des comportements personnalisés à Keycloak.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus