Edit a geojson in a leaflet map and save it in the model

Dear Community,
I have created a django app that allow me to:

  1. Create a polygon
  2. Delete a polygon

Now i am getting a lot of problem to figure it out how to edit the polygon saved and then after the editing i would like to save it

This is my models.py

#Very easy
from django.contrib.gis.db import models

class Polygon(models.Model):
    name = models.CharField(max_length=255)
    geometry = models.PolygonField()

This is my views.py

def polygon_update(request, pk):
    polygon = get_object_or_404(Polygon, pk=pk)
    print(polygon.geometry)
    # SRID=4326;POLYGON ((-0.047023 51.490095, -0.058463 51.506837, -0.073792 51.498574, -0.077796 51.487601, -0.047023 51.490095))
    print(type(polygon.geometry))
# <class 'django.contrib.gis.geos.polygon.Polygon'>    
    if request.method == 'POST':
        name = request.POST['name']
        geometry = request.POST['geometry']
        polygon.name = name
        polygon.geometry = GEOSGeometry(geometry)
        polygon.save()
        return redirect('polygon_list')
    
    return render(request, 'mapapp/polygon_update.html', {'polygon': polygon})

This is my template

{% extends 'base.html' %}

{% block content %}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Modifica GeoJSON su Leaflet</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <style>
        #map {
            height: 400px;
        }
    </style>
</head>
<body>
    <div id="map"></div>

    <button id="startEditing">Inizia l'editing</button>
    <button id="stopEditing" disabled>Termina l'editing</button>
    <button id="salvaGeoJSON" disabled>Salva GeoJSON</button>

    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/turf/6.3.0/turf.min.js"></script> <!-- Libreria Turf.js per le operazioni GIS -->
    <script>
        var map = L.map('map').setView([0, 0], 2); // Imposta la vista della mappa

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map);

        var geoJSONLayer;
        var editableLayers = new L.FeatureGroup();
        map.addLayer(editableLayers);

        // Funzione per avviare l'editing
        document.getElementById('startEditing').addEventListener('click', function () {
            map.addLayer(editableLayers);
            document.getElementById('startEditing').disabled = true;
            document.getElementById('stopEditing').disabled = false;
            document.getElementById('salvaGeoJSON').disabled = false;
        });

        // Funzione per terminare l'editing
        document.getElementById('stopEditing').addEventListener('click', function () {
            map.removeLayer(editableLayers);
            document.getElementById('startEditing').disabled = false;
            document.getElementById('stopEditing').disabled = true;
            document.getElementById('salvaGeoJSON').disabled = true;
        });

        // Funzione per salvare il GeoJSON
        document.getElementById('salvaGeoJSON').addEventListener('click', function () {
            var modifiedGeoJSON = editableLayers.toGeoJSON(); // Converte i dati modificati in GeoJSON
            console.log(JSON.stringify(modifiedGeoJSON));

            // Ora puoi inviare il GeoJSON modificato al server o fare altro con esso.

            alert("GeoJSON modificato salvato!");
        });

        // Esempio di GeoJSON da visualizzare e modificare
        var sampleGeoJSON = {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "properties": {},
                "geometry": {
                    {{polygon.geometry}}
                }
            }]
        };

        geoJSONLayer = L.geoJSON(sampleGeoJSON, {
            onEachFeature: function (feature, layer) {
                editableLayers.addLayer(layer);
            }
        });

        map.addLayer(geoJSONLayer);
    </script>
</body>
</html>


{% endblock %}

Can someone help me to figure it out how to do it?

I think two components should ease a lot what you are doing mostly manually: django-leaflet and a real Django form. Have a look at https://django-leaflet.readthedocs.io/

Thanks for the suggestion @claudep.

I have tried to use django-leaflet but i have got this error.

[07/Sep/2023 12:49:09] "GET /edit_field/1/ HTTP/1.1" 404 2960
Internal Server Error: /edit/
Traceback (most recent call last):
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\core\handlers\exception.py", line 55, in inner  
    response = get_response(request)
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Utente\Desktop\djangohow_leaflet\app\djangoleaflet\views.py", line 13, in formdjangoleaflet
    return render(request, "djangoleaflet/djangoleaflet.html", {"form",form})
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\shortcuts.py", line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\template\loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\template\backends\django.py", line 57, in render
    context = make_context(
  File "C:\Users\Utente\AppData\Roaming\Python\Python310\site-packages\django\template\context.py", line 278, in make_context 
    raise TypeError(
TypeError: context must be a dict rather than set.
[07/Sep/2023 12:49:12] "GET /edit/ HTTP/1.1" 500 88101

this is my model.py

from django.contrib.gis.db import models

class WeatherStation(models.Model):
    name = models.CharField(max_length=255)
    geom = models.PointField()

this is my views.py

from django.shortcuts import render

# Create your views here.

from .forms import WeatherStationForm

def formdjangoleaflet(request):
    form=WeatherStationForm(request)
    if request.method=="POST":
        if form.is_valid():
            print(form)
        
    return render(request, "djangoleaflet/djangoleaflet.html", {"form",form})

this is my urls.py

from django.contrib import admin
from django.urls import path, include
from djangoleaflet.views import formdjangoleaflet

urlpatterns = [
    path("edit/", formdjangoleaflet, name="edit")
]

this is my template

{% load leaflet_tags %}
<html>
  <head>
   {% leaflet_js plugins="forms" %}
   {% leaflet_css plugins="forms" %}
  </head>
  <body>
    <h1>Edit {{ object }}</h1>
    <form method="POST">
        {{ form }}
        <input type="submit"/>
    </form>
  </body>
</html>

Could you please say to me what am i doing wrong?

Hum… :stuck_out_tongue_winking_eye:

1 Like

Actually you were right.

django-leaflet just love.

hi, what is it WeatherStationForm your?