After the previous article regarding Django, Leaflet and GeoJSON, I wanted to highlight the simplicity of GeoDjango geometries creation and edition with django-leaflet.
It relies on Leaflet.draw for user interactions.
note: | Until recently, it was restricted to Django 1.6+, but Gaël contributed a backport that allows Django 1.4.2+ users to have them too ! |
---|
In Django Adminsite
Given a GeoDjango model as usual
# models.py
from django.db import models
from django.contrib.gis.db import models as gismodels
class MushroomSpot(gismodels.Model):
name = models.CharField(max_length=256)
geom = gismodels.PolygonField()
objects = gismodels.GeoManager()
def __unicode__(self):
return self.name
Register using Leaflet GeoAdmin
It's as simple as :
from django.contrib import admin
from leaflet.admin import LeafletGeoAdmin
from .models import MushroomSpot
admin.site.register(MushroomSpot, LeafletGeoAdmin)
In forms views
Edition view usign Class-Based View
from django import forms
from django.views.generic import UpdateView
from leaflet.forms.widgets import LeafletWidget
from .models import MushroomSpot
class MushroomSpotForm(forms.ModelForm):
class Meta:
model = MushroomSpot
fields = ('name', 'geom')
widgets = {'geom': LeafletWidget()}
class EditMushroomSpot(UpdateView):
model = MushroomSpot
form_class = MushroomSpotForm
template_name = 'form.html'
Form template with Leaflet tags
{% load leaflet_tags %}
<html>
<head>
{% leaflet_js plugins="forms" %}
{% leaflet_css plugins="forms" %}
</head>
<body>
<h1>Edit {{ object }}</h1>
<form method="POST">
{{ form }}
{% csrf_token %}
<input type="submit"/>
</form>
</body>
</html>
Going further...
The Django form widget has a couple of options, that can tweak some aspects of the map (size, read-only, ...).
But some advanced usage might require specific interactions or behaviour, beyond Django field and widgets customizations.
Custom field JavaScript component
The frontend field component behaviour and initialization is also pluggable, and can be used to add extra controls, layers or whatever.
Custom.GeometryField = L.GeometryField.extend({
addTo: function (map) {
L.GeometryField.prototype.addTo.call(this, map);
var filecontrol = map.filecontrol = L.Control.fileLayerLoad();
map.addControl(filecontrol);
}
});
class CustomLeafletWidget(LeafletWidget):
geometry_field_class = 'Custom.GeometryField'
Custom de/serialization of form field value
The Javascript component for de/serializing fields value is pluggable, can be used to override the way the geometries are sent to the form.
Custom.FieldStore = L.FieldStore({
save: function (layer) {
this.formfield.value = {"latlngs": layer.getLatLngs()};
}
});
class CustomLeafletWidget(LeafletWidget):
field_store_class = 'Custom.FieldStore'
Help us improve django-leaflet !
We built django-leaflet at Makina Corpus for some our Webmapping projects. It is used in production and gives us satisfaction in most use-cases.
If our initial design does not match your needs, please tell us what you think !
For example, personnally, I would like to remove the <script> tag in the map template, and pass configuration entries through the DOM instead...
...your turn !
#django, #leaflet, #gis, #geojson - Posted in the Dev category