Compare commits
15 Commits
b0f72584e2
..
Docker
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a8d20047f | |||
| 112b74f5cd | |||
| 22a92cb3df | |||
| 74d4ee49cc | |||
| f5aaac2acf | |||
| 775e40e9ae | |||
| e794f3fff2 | |||
| b4f2e3232a | |||
| e8b583d4c6 | |||
| b9c453fdd2 | |||
| 625c591122 | |||
| f551763798 | |||
| f57fa4cc20 | |||
| 08884cb370 | |||
| 9b5defec6d |
@@ -6,6 +6,7 @@ Created on: 24.01.22
|
||||
|
||||
"""
|
||||
import json
|
||||
import uuid
|
||||
from abc import abstractmethod
|
||||
|
||||
from django.contrib.gis import geos
|
||||
@@ -155,6 +156,9 @@ class AbstractModelAPISerializer:
|
||||
if isinstance(geojson, dict):
|
||||
geojson = json.dumps(geojson)
|
||||
geometry = geos.fromstr(geojson)
|
||||
is_4326 = Geometry.is_valid_4326(geometry)
|
||||
if not is_4326:
|
||||
raise ValueError("Geometry not in EPSG:4326 (WGS84). Unknown spatial reference system.")
|
||||
geometry = Geometry.cast_to_rlp_srid(geometry)
|
||||
geometry = Geometry.cast_to_multipolygon(geometry)
|
||||
return geometry
|
||||
@@ -171,13 +175,20 @@ class AbstractModelAPISerializer:
|
||||
Returns:
|
||||
|
||||
"""
|
||||
if not id:
|
||||
raise ValueError("No id provided. The id is expected to live in the URL!")
|
||||
|
||||
# First if there is an external identifier linked to an internal one, so we can continue with the internal
|
||||
try:
|
||||
ext_id = ExternalIdentifier.objects.get(external_id=id)
|
||||
id = ext_id.internal_id
|
||||
except ObjectDoesNotExist:
|
||||
# No external id found - let's hope the given id exists internally
|
||||
pass
|
||||
# Not found as external id - let's check whether this is a valid uuid and therefore
|
||||
# potentially an internal id
|
||||
try:
|
||||
uuid.UUID(id)
|
||||
except ValueError:
|
||||
raise AssertionError(f"'{id}' is neither a known external identifier nor a valid uuid.")
|
||||
|
||||
obj = self.model.objects.get(
|
||||
id=id,
|
||||
@@ -217,7 +228,11 @@ class AbstractModelAPISerializer:
|
||||
conflict_geometries = geometry.get_conflict_geometries()
|
||||
for geom in conflict_geometries:
|
||||
try:
|
||||
data = geom.get_data_objects(["identifier", "id"])[0]
|
||||
data = geom.get_data_objects(["identifier", "id"])
|
||||
if len(data) == 0:
|
||||
# expected behaviour in case of deleted data object
|
||||
continue
|
||||
data = data[0]
|
||||
except KeyError:
|
||||
raise AssertionError(f"Geometry {geom.id} is not attached to any entries. Contact an admin!")
|
||||
ids.append(
|
||||
|
||||
+28
-31
@@ -10,6 +10,7 @@ from json import JSONDecodeError
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import JsonResponse, HttpRequest
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from api.utils.serializer.v1.compensation import CompensationAPISerializerV1
|
||||
from api.utils.serializer.v1.deduction import DeductionAPISerializerV1
|
||||
@@ -28,6 +29,20 @@ class AbstractAPIViewV1(AbstractAPIView):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.serializer = self.serializer()
|
||||
|
||||
@csrf_exempt
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
except (JSONDecodeError,
|
||||
AssertionError,
|
||||
ValueError,
|
||||
PermissionError) as e:
|
||||
return self._return_error_response(e, 400)
|
||||
except ObjectDoesNotExist as e:
|
||||
return self._return_error_response(e, 404)
|
||||
except Exception as e:
|
||||
return self._return_error_response(e, 500)
|
||||
|
||||
def get(self, request: HttpRequest, id=None):
|
||||
""" Handles the GET request
|
||||
|
||||
@@ -40,17 +55,12 @@ class AbstractAPIViewV1(AbstractAPIView):
|
||||
Returns:
|
||||
response (JsonResponse)
|
||||
"""
|
||||
try:
|
||||
self.rpp = int(request.GET.get("rpp", self.rpp))
|
||||
self.page_number = int(request.GET.get("p", self.page_number))
|
||||
|
||||
self.serializer.rpp = self.rpp
|
||||
self.serializer.page_number = self.page_number
|
||||
|
||||
self.serializer.prepare_lookup(id, self.user)
|
||||
data = self.serializer.fetch_and_serialize()
|
||||
except Exception as e:
|
||||
return self._return_error_response(e, 500)
|
||||
self.rpp = int(request.GET.get("rpp", self.rpp))
|
||||
self.page_number = int(request.GET.get("p", self.page_number))
|
||||
self.serializer.rpp = self.rpp
|
||||
self.serializer.page_number = self.page_number
|
||||
self.serializer.prepare_lookup(id, self.user)
|
||||
data = self.serializer.fetch_and_serialize()
|
||||
return self._return_response(request, data)
|
||||
|
||||
def post(self, request: HttpRequest):
|
||||
@@ -64,16 +74,9 @@ class AbstractAPIViewV1(AbstractAPIView):
|
||||
Returns:
|
||||
response (JsonResponse)
|
||||
"""
|
||||
try:
|
||||
body = request.body.decode("utf-8")
|
||||
body = json.loads(body)
|
||||
created_id = self.serializer.create_model_from_json(body, self.user)
|
||||
except (JSONDecodeError,
|
||||
AssertionError,
|
||||
ValueError,
|
||||
PermissionError,
|
||||
ObjectDoesNotExist) as e:
|
||||
return self._return_error_response(e, 400)
|
||||
body = request.body.decode("utf-8")
|
||||
body = json.loads(body)
|
||||
created_id = self.serializer.create_model_from_json(body, self.user)
|
||||
return JsonResponse({"id": created_id})
|
||||
|
||||
def put(self, request: HttpRequest, id=None):
|
||||
@@ -88,12 +91,9 @@ class AbstractAPIViewV1(AbstractAPIView):
|
||||
Returns:
|
||||
response (JsonResponse)
|
||||
"""
|
||||
try:
|
||||
body = request.body.decode("utf-8")
|
||||
body = json.loads(body)
|
||||
updated_id = self.serializer.update_model_from_json(id, body, self.user)
|
||||
except Exception as e:
|
||||
return self._return_error_response(e, 500)
|
||||
body = request.body.decode("utf-8")
|
||||
body = json.loads(body)
|
||||
updated_id = self.serializer.update_model_from_json(id, body, self.user)
|
||||
return JsonResponse({"id": updated_id})
|
||||
|
||||
def delete(self, request: HttpRequest, id=None):
|
||||
@@ -107,10 +107,7 @@ class AbstractAPIViewV1(AbstractAPIView):
|
||||
response (JsonResponse)
|
||||
"""
|
||||
|
||||
try:
|
||||
success = self.serializer.delete_entry(id, self.user)
|
||||
except Exception as e:
|
||||
return self._return_error_response(e, 500)
|
||||
success = self.serializer.delete_entry(id, self.user)
|
||||
return JsonResponse(
|
||||
{
|
||||
"success": success,
|
||||
|
||||
+35
-10
@@ -113,7 +113,7 @@ class Geometry(BaseResource):
|
||||
objs (list): The list of objects
|
||||
"""
|
||||
objs = []
|
||||
|
||||
stop_searching = False
|
||||
# Some related data sets can be processed rather easily
|
||||
regular_sets = [
|
||||
self.intervention_set,
|
||||
@@ -129,15 +129,20 @@ class Geometry(BaseResource):
|
||||
else:
|
||||
objs += set_objs
|
||||
|
||||
# ... but we need a special treatment for compensations, since they can be deleted directly OR inherit their
|
||||
# de-facto-deleted status from their deleted parent intervention
|
||||
comp_objs = self.compensation_set.filter(
|
||||
Q(deleted=None) & Q(intervention__deleted=None)
|
||||
)
|
||||
if limit_to_attrs:
|
||||
objs += comp_objs.values(*limit_to_attrs)
|
||||
else:
|
||||
objs += comp_objs
|
||||
stop_searching = len(objs) > 0
|
||||
if stop_searching:
|
||||
break
|
||||
|
||||
if not stop_searching:
|
||||
# ... but we need a special treatment for compensations, since they can be deleted directly OR inherit their
|
||||
# de-facto-deleted status from their deleted parent intervention
|
||||
comp_objs = self.compensation_set.filter(
|
||||
Q(deleted=None) | Q(intervention__deleted=None)
|
||||
)
|
||||
if limit_to_attrs:
|
||||
objs += comp_objs.values(*limit_to_attrs)
|
||||
else:
|
||||
objs += comp_objs
|
||||
return objs
|
||||
|
||||
def get_data_object(self, limit_to_attrs: list = None):
|
||||
@@ -457,6 +462,26 @@ class Geometry(BaseResource):
|
||||
conflict_geoms = Geometry.objects.filter(id__in=conflict_geoms_id)
|
||||
return conflict_geoms
|
||||
|
||||
@staticmethod
|
||||
def is_valid_4326(geometry):
|
||||
""" Checks whether a given geometry's coordinates are in a valid range to be of EPSG:4326
|
||||
|
||||
Args:
|
||||
geometry: The geometry
|
||||
|
||||
Returns:
|
||||
ret_val (bool): Whether the geometry is valid EPSG:4326
|
||||
"""
|
||||
if not geometry.centroid.coords:
|
||||
# No coordinates at all found, therefore technically proper 4326
|
||||
return True
|
||||
|
||||
try:
|
||||
lat,lon = geometry.centroid.coords
|
||||
return (-90.0 <= lat <= 90.0) and (-180.0 <= lon <= 180.0)
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
|
||||
class GeometryConflict(UuidModel):
|
||||
"""
|
||||
|
||||
@@ -85,12 +85,6 @@ class GeometryTestCase(BaseTestCase):
|
||||
)
|
||||
|
||||
def test_get_data_objects(self):
|
||||
num_objs_with_geom = 0
|
||||
self.assertEqual(
|
||||
len(self.geom_1.get_data_objects()),
|
||||
num_objs_with_geom
|
||||
)
|
||||
|
||||
objs = [
|
||||
self.intervention,
|
||||
self.compensation,
|
||||
@@ -98,16 +92,13 @@ class GeometryTestCase(BaseTestCase):
|
||||
self.ema,
|
||||
]
|
||||
for obj in objs:
|
||||
obj.geometry = self.geom_1
|
||||
obj.save()
|
||||
if not obj.geometry:
|
||||
obj.geometry = Geometry.objects.create(geom=self.create_dummy_geometry())
|
||||
obj.save()
|
||||
|
||||
num_objs_with_geom += 1
|
||||
geom_objs = self.geom_1.get_data_objects()
|
||||
self.assertEqual(
|
||||
len(geom_objs),
|
||||
num_objs_with_geom
|
||||
)
|
||||
self.assertIn(obj, geom_objs)
|
||||
data_objs = obj.geometry.get_data_objects()
|
||||
self.assertEqual(len(data_objs), 1)
|
||||
self.assertIn(obj, data_objs)
|
||||
|
||||
def test_as_feature_collection(self):
|
||||
geometry = self.geom_1.geom
|
||||
|
||||
@@ -56,11 +56,9 @@
|
||||
],
|
||||
"layers":
|
||||
[
|
||||
{ "id": "webatlas_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP farbig", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_WebAtlasRP/MapServer/WmsServer?", "name": "RP_WebAtlasRP", "active": true},
|
||||
{ "id": "webatlas_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP grau", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_ETRS_Gt/MapServer/WmsServer?", "name": "0", "active": false },
|
||||
{ "id": "luftbilder", "folder": "bg", "type": "WMS", "order": -1, "title": "Luftbilder", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/rp_dop20.fcgi?", "name": "rp_dop20", "active": false },
|
||||
{ "id": "basemap_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE farbig", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_farbe", "active": false },
|
||||
{ "id": "basemap_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE grau", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_grau", "active": false },
|
||||
{ "id": "basemap_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE grau", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_grau", "active": true },
|
||||
{ "id": "dtk_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "DTK5 farbig", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5", "active": false },
|
||||
{ "id": "dtk_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "DTK5 grau", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5_grau", "active": false },
|
||||
|
||||
|
||||
Reference in New Issue
Block a user