Compare commits

..

6 Commits

Author SHA1 Message Date
mpeltriaux 625c591122 # Tests
* updates tests
* enhances workflow of geometry conflict fetching
2026-06-25 08:55:50 +02:00
mpeltriaux f551763798 # Performance boost
* boosts performance of geometry conflict fetching 50-75%
2026-06-25 08:27:09 +02:00
mpeltriaux 08884cb370 Merge pull request '# HOTFIX' (#550) from hotfix_indexErrorOnAPIGet into master
Reviewed-on: #550
2026-06-20 12:10:51 +02:00
mpeltriaux 9b5defec6d # HOTFIX
* fixes bug where unfetchable data entries of a GeometryConflict would result in an error via API
2026-06-20 12:10:13 +02:00
mpeltriaux 0425430e65 Merge pull request '# HOTFIX' (#547) from hotfix_indexErrorOnAPIGet into master
Reviewed-on: #547
2026-06-20 09:27:55 +02:00
mpeltriaux fec313445d # HOTFIX
* fixes a bug where detected GeometryConflicts with deleted entries would case an IndexError
2026-06-20 09:27:02 +02:00
4 changed files with 42 additions and 29 deletions
+5 -1
View File
@@ -217,7 +217,11 @@ class AbstractModelAPISerializer:
conflict_geometries = geometry.get_conflict_geometries() conflict_geometries = geometry.get_conflict_geometries()
for geom in conflict_geometries: for geom in conflict_geometries:
try: 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: except KeyError:
raise AssertionError(f"Geometry {geom.id} is not attached to any entries. Contact an admin!") raise AssertionError(f"Geometry {geom.id} is not attached to any entries. Contact an admin!")
ids.append( ids.append(
+19 -3
View File
@@ -113,7 +113,7 @@ class Geometry(BaseResource):
objs (list): The list of objects objs (list): The list of objects
""" """
objs = [] objs = []
stop_searching = False
# Some related data sets can be processed rather easily # Some related data sets can be processed rather easily
regular_sets = [ regular_sets = [
self.intervention_set, self.intervention_set,
@@ -129,10 +129,15 @@ class Geometry(BaseResource):
else: else:
objs += set_objs objs += set_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 # ... 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 # de-facto-deleted status from their deleted parent intervention
comp_objs = self.compensation_set.filter( comp_objs = self.compensation_set.filter(
Q(deleted=None) & Q(intervention__deleted=None) Q(deleted=None) | Q(intervention__deleted=None)
) )
if limit_to_attrs: if limit_to_attrs:
objs += comp_objs.values(*limit_to_attrs) objs += comp_objs.values(*limit_to_attrs)
@@ -142,11 +147,22 @@ class Geometry(BaseResource):
def get_data_object(self, limit_to_attrs: list = None): def get_data_object(self, limit_to_attrs: list = None):
""" """
Getter for the specific data object which is related to this geometry Getter for the specific data object which is related to this geometry.
!!! Only returns undeleted entries !!!
Returns:
result (str|None): Returns the desired attributes or None if the data object is marked as deleted
""" """
objs = self.get_data_objects(limit_to_attrs) objs = self.get_data_objects(limit_to_attrs)
assert (len(objs) <= 1) assert (len(objs) <= 1)
try:
result = objs.pop() result = objs.pop()
except IndexError:
# If this happens, we just processed a GeometryConflict with an entry which is marked as deleted.
# Therefore we return None
result = None
return result return result
def update_parcels(self): def update_parcels(self):
+3 -1
View File
@@ -679,7 +679,9 @@ class GeoReferencedMixin(models.Model):
conflicting_geometries = self.geometry.get_conflict_geometries() conflicting_geometries = self.geometry.get_conflict_geometries()
data_object_identifiers = [] data_object_identifiers = []
for conflicting_geom in conflicting_geometries: for conflicting_geom in conflicting_geometries:
data_object_identifiers.append(conflicting_geom.get_data_object(["identifier"])) data_obj_id = conflicting_geom.get_data_object(["identifier"])
if data_obj_id:
data_object_identifiers.append(data_obj_id)
add_message = len(data_object_identifiers) > 0 add_message = len(data_object_identifiers) > 0
if add_message: if add_message:
+5 -14
View File
@@ -85,12 +85,6 @@ class GeometryTestCase(BaseTestCase):
) )
def test_get_data_objects(self): 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 = [ objs = [
self.intervention, self.intervention,
self.compensation, self.compensation,
@@ -98,16 +92,13 @@ class GeometryTestCase(BaseTestCase):
self.ema, self.ema,
] ]
for obj in objs: for obj in objs:
obj.geometry = self.geom_1 if not obj.geometry:
obj.geometry = Geometry.objects.create(geom=self.create_dummy_geometry())
obj.save() obj.save()
num_objs_with_geom += 1 data_objs = obj.geometry.get_data_objects()
geom_objs = self.geom_1.get_data_objects() self.assertEqual(len(data_objs), 1)
self.assertEqual( self.assertIn(obj, data_objs)
len(geom_objs),
num_objs_with_geom
)
self.assertIn(obj, geom_objs)
def test_as_feature_collection(self): def test_as_feature_collection(self):
geometry = self.geom_1.geom geometry = self.geom_1.geom