diff options
Diffstat (limited to 'ishtar_common/admin.py')
-rw-r--r-- | ishtar_common/admin.py | 165 |
1 files changed, 98 insertions, 67 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 50dbbe25a..36331e2f7 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -229,7 +229,7 @@ def export_as_csv_action( def export_as_geojson_action( geometry_field, - description=_("Export selected as GeoJSON file"), + description=_("Export selected as GeoJSON/JSON file"), fields=None, exclude=None, ): @@ -243,24 +243,29 @@ def export_as_geojson_action( Generic zipped geojson export admin action. """ opts = modeladmin.model._meta - field_names = set( - [field.name for field in opts.fields if field.name != geometry_field] - ) - if fields: - fieldset = set(fields) - field_names = field_names & fieldset - if exclude: - excludeset = set(exclude) - field_names = field_names - excludeset + if hasattr(modeladmin.model, "geodata_export"): + geojson = [] + for item in queryset.order_by("pk").all(): + geojson += item.geodata_export + geojson = json.dumps(geojson, indent=4) + else: + field_names = set( + [field.name for field in opts.fields if field.name != geometry_field] + ) + if fields: + fieldset = set(fields) + field_names = field_names & fieldset + if exclude: + excludeset = set(exclude) + field_names = field_names - excludeset + geojson = serialize( + "geojson", + queryset.order_by("pk"), + geometry_field=geometry_field, + fields=field_names, + ).encode("utf-8") basename = str(opts).replace(".", "_") - - geojson = serialize( - "geojson", - queryset.order_by("pk"), - geometry_field=geometry_field, - fields=field_names, - ).encode("utf-8") in_memory = BytesIO() czip = zipfile.ZipFile(in_memory, "a") czip.writestr(basename + ".geojson", geojson) @@ -1234,7 +1239,7 @@ class ImportActionAdmin(admin.ModelAdmin): class ImportGeoJsonForm(forms.Form): json_file = forms.FileField( - label=_("Geojson file"), + label=_("Geojson/JSON file"), help_text=_( "Only unicode encoding is managed - convert your" " file first. The file must be a geojson file or a zip " @@ -1312,11 +1317,11 @@ class ImportGEOJSONActionAdmin(object): self.message_user(request, error, level=messages.ERROR) return False if geom.geom_type == "Point": - values["center"] = geom + values["point_2d"] = geom elif geom.geom_type == "MultiPolygon": - values["limit"] = geom + values["multi_polygon"] = geom elif geom.geom_type == "Polygon": - values["limit"] = MultiPolygon(geom) + values["multi_polygon"] = MultiPolygon(geom) else: if trace_error: error = str(_("Geometry {} not managed for towns - feature {}")).format( @@ -1355,7 +1360,8 @@ class ImportGEOJSONActionAdmin(object): if form.is_valid(): json_file_obj = request.FILES["json_file"] - base_dct = {"file_form": form, "current_action": "import_geojson"} + base_dct = {"file_form": form, "current_action": "import_geojson", + "is_town": True} tempdir = tempfile.mkdtemp() tmpfilename = tempdir + os.sep + "dest_file" @@ -1389,53 +1395,78 @@ class ImportGEOJSONActionAdmin(object): "insee_prefix": request.POST.get("numero_insee_prefix", None) or "", "surface_unit": int(request.POST.get("surface_unit")), } + town_content_type = ContentType.objects.get( + app_label="ishtar_common", model="town" + ) + town_data_type, __ = models.GeoDataType.objects.get_or_create( + txt_idx="town-limit", defaults={"label": _("Town limit")} + ) with open(json_filename) as json_file_obj: json_file = json_file_obj.read() - try: - dct = json.loads(json_file) - if "features" not in dct or not dct["features"]: - raise ValueError() - except (ValueError, AssertionError): - error = _("Bad geojson file") - return self.import_geojson_error( - request, error, base_dct, tempdir - ) - - error_count = 0 - created = 0 - updated = 0 - for idx, feat in enumerate(dct["features"]): - trace_error = True - if error_count == 6: - self.message_user( - request, _("Too many errors..."), level=messages.ERROR + dct = json.loads(json_file) + if "features" not in dct or not dct["features"]: + # probably Ishtar JSON + created, __, updated, __ = models.Town.geodata_import(dct) + else: + error_count = 0 + created = 0 + updated = 0 + for idx, feat in enumerate(dct["features"]): + trace_error = True + if error_count == 6: + self.message_user( + request, _("Too many errors..."), level=messages.ERROR + ) + if error_count > 5: + trace_error = False + values = self.geojson_values( + request, idx + 1, feat, keys, trace_error ) - if error_count > 5: - trace_error = False - values = self.geojson_values( - request, idx + 1, feat, keys, trace_error - ) - if not values: - error_count += 1 - continue - num_insee = values.pop("numero_insee") - year = values.pop("year") or None - t, c = models_common.Town.objects.get_or_create( - numero_insee=num_insee, year=year, defaults=values - ) - if c: - created += 1 - else: - modified = False - for k in values: - if keys["update"] and k not in ["center", "limit"]: - continue - if values[k] != getattr(t, k): - setattr(t, k, values[k]) - modified = True - if modified: - updated += 1 - t.save() + if not values: + error_count += 1 + continue + num_insee = values.pop("numero_insee") + year = values.pop("year") or None + geo_values = {} + for k in ["point_2d", "multi_polygon"]: + if k in values: + geo_values[k] = values.pop(k) + t, c = models_common.Town.objects.get_or_create( + numero_insee=num_insee, year=year, defaults=values + ) + if c: + created += 1 + else: + modified = False + if not keys["update"]: + for k in values: + if not getattr(t, k) or \ + values[k] != getattr(t, k): + setattr(t, k, values[k]) + modified = True + if modified: + updated += 1 + t.save() + if geo_values: + if t.main_geodata: # update + for k in geo_values: + c_value = getattr(t.main_geodata, k) + if not c_value or \ + geo_values[k] != c_value.wkt: + setattr(t.main_geodata, k, geo_values[k]) + t.main_geodata.save() + else: + gd, __ = models.GeoVectorData.objects.get_or_create( + source_id=t.pk, + source_content_type=town_content_type, + data_type=town_data_type, + defaults={"name": t.cached_label} + ) + for k in geo_values: + setattr(gd, k, geo_values[k]) + gd.save() + t.main_geodata = gd + t.save() if created: self.message_user( request, str(_("%d item(s) created.")) % created @@ -1455,7 +1486,7 @@ class ImportGEOJSONActionAdmin(object): return render( request, "admin/import_from_file.html", - {"file_form": form, "current_action": "import_geojson"}, + {"file_form": form, "current_action": "import_geojson", "is_town": True}, ) |