From 608532dfcde97a984ed10ad60a01e0210be65d0d Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 16 Jan 2023 16:43:21 +0100 Subject: GeoVectorData: method to update from a geojson --- ishtar_common/models_common.py | 49 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'ishtar_common/models_common.py') diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 151ab5650..a6f9ac0e8 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -8,6 +8,7 @@ Generic models and tools for models import copy from collections import OrderedDict import datetime +import fiona import json import logging import os @@ -25,7 +26,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from django.db import migrations as db_migrations from django.contrib.gis.db import models -from django.contrib.gis.geos import Point +from django.contrib.gis.geos import GEOSGeometry, Point from django.contrib.gis.gdal.error import GDALException from django.contrib.postgres.fields import JSONField from django.contrib.postgres.search import SearchVectorField, SearchVector @@ -2117,6 +2118,17 @@ GEOMETRY_TYPE_LBL = { } +GEOTYPE_TO_GEOVECTOR = { + # key: (geom attr, need list convert) + "Point": ("point_2d", False), + "LineString": ("multi_line", True), + "Polygon": ("multi_polygon", True), + "MultiPoint": ("multi_points", False), + "MultiLineString": ("multi_line", False), + "MultiPolygon": ("multi_polygon", False), +} + + class GeoVectorData(Imported, OwnPerms): SLUG = "geovectordata" RELATED_MODELS = [ @@ -2589,6 +2601,41 @@ class GeoVectorData(Imported, OwnPerms): return self._geojson_serialize("multi_polygon") return "{}" + def update_from_geojson(self, geojson: str, save=False) -> bool: + """ + Update geometry from a geojson string + :param geojson: geojson + :param save: save the object if set to True + :return: True if update + """ + if not geojson: # no data provided + return False + + with fiona.open(geojson) as src: + if len(src) != 1: + # ambiguous -> need only one feature + return False + feature = src[0] + geom = feature["geometry"] + if geom["type"] not in GEOTYPE_TO_GEOVECTOR: + # unknown geometry type + return False + feature_attr, need_list_convert = GEOTYPE_TO_GEOVECTOR[geom["type"]] + if need_list_convert: + geom["coordinates"] = [geom["coordinates"]] + geom = json.dumps(geom) + setattr(self, feature_attr, GEOSGeometry(geom)) + if save: + self.save() + geo_attrs = ["point_2d", "point_3d", "x", "y", "z", "multi_line", + "multi_points", "multi_polygon"] + geo_attrs.pop(geo_attrs.index(feature_attr)) + for geo_attr in geo_attrs: + setattr(self, geo_attr, None) + if save: + self.save() + return True + @classmethod def migrate_srid(cls, new_srid): fields = ( -- cgit v1.2.3