diff --git a/geotrek/api/v2/serializers.py b/geotrek/api/v2/serializers.py index 656b1fc79e..4917b3f285 100644 --- a/geotrek/api/v2/serializers.py +++ b/geotrek/api/v2/serializers.py @@ -2095,7 +2095,9 @@ class SignageSerializer(DynamicFieldsMixin, serializers.ModelSerializer): read_only=True, source="geom3d_transformed", precision=7 ) attachments = AttachmentSerializer(many=True) - blades = BladeSerializer(source="blades_set", many=True) + # TODO: why did it use to refer to the related name `blades_set` for + # the `topology` field of Blade? + blades = BladeSerializer(source="blade_set", many=True) provider = serializers.SlugRelatedField(read_only=True, slug_field="name") condition = serializers.SerializerMethodField( help_text=_( diff --git a/geotrek/maintenance/templates/maintenance/sql/post_10_interventions.sql b/geotrek/maintenance/templates/maintenance/sql/post_10_interventions.sql index 91f1a61309..76ee17615e 100644 --- a/geotrek/maintenance/templates/maintenance/sql/post_10_interventions.sql +++ b/geotrek/maintenance/templates/maintenance/sql/post_10_interventions.sql @@ -32,6 +32,8 @@ BEGIN END; $$ LANGUAGE plpgsql; +-- TODO: this function is never called +-- Its trigger was removed in this PR: https://github.com/GeotrekCE/Geotrek-admin/pull/2218 CREATE FUNCTION {{ schema_geotrek }}.delete_related_intervention_blade() RETURNS trigger SECURITY DEFINER AS $$ BEGIN UPDATE maintenance_intervention SET deleted = NEW.deleted WHERE target_id = NEW.id AND target_type_id IN (SELECT id FROM django_content_type AS ct WHERE ct.model = 'blade'); diff --git a/geotrek/signage/filters.py b/geotrek/signage/filters.py index 32e12326fa..495d93c927 100644 --- a/geotrek/signage/filters.py +++ b/geotrek/signage/filters.py @@ -84,7 +84,7 @@ def filter_intervention_year(self, qs, name, value): class BladeFilterSet(MapEntityFilterSet): - bbox = PolygonTopologyFilter(field_name="topology", lookup_expr="intersects") + bbox = PolygonTopologyFilter(field_name="signage__topo_object", lookup_expr="intersects") structure = ModelMultipleChoiceFilter( field_name="signage__structure", queryset=Structure.objects.all(), diff --git a/geotrek/signage/forms.py b/geotrek/signage/forms.py index 6766e97f45..7aaad991b6 100644 --- a/geotrek/signage/forms.py +++ b/geotrek/signage/forms.py @@ -54,7 +54,6 @@ class Meta: class BaseBladeForm(CommonForm): - geomfields = ["topology"] fieldslayout = ( [ @@ -96,7 +95,6 @@ def __init__(self, *args, **kwargs): del self.fields["direction"] def save(self, *args, **kwargs): - self.instance.set_topology(self.signage) self.instance.signage = self.signage return super(CommonForm, self).save(*args, **kwargs) @@ -132,38 +130,9 @@ class Meta: fields = ["id", "number", "direction", "type", "conditions", "color"] -if settings.TREKKING_TOPOLOGY_ENABLED: - - class BladeForm(BaseBladeForm): - topology = TopologyField(label="") - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.fields["topology"].initial = self.signage - self.fields["topology"].widget.modifiable = True - self.fields["topology"].label = "{}{} {}".format( - self.instance.signage_display, - _("On %s") % _(self.signage.kind.lower()), - f'{self.signage!s}', - ) - -else: - - class BladeForm(BaseBladeForm): - topology = GeometryField(label="") - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.fields["topology"].initial = self.signage.geom - self.fields["topology"].widget = MapWidget(attrs={"geom_type": "POINT"}) - self.fields["topology"].widget.modifiable = False - self.fields["topology"].label = "{}{} {}".format( - self.instance.signage_display, - _("On %s") % _(self.signage.kind.lower()), - f'{self.signage!s}', - ) +class BladeForm(BaseBladeForm): + # TODO: display uneditable map + ... if settings.TREKKING_TOPOLOGY_ENABLED: diff --git a/geotrek/signage/migrations/0045_remove_blade_topology.py b/geotrek/signage/migrations/0045_remove_blade_topology.py new file mode 100644 index 0000000000..df5ae6aa7d --- /dev/null +++ b/geotrek/signage/migrations/0045_remove_blade_topology.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.23 on 2025-08-19 10:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('signage', '0044_auto_20250611_1417'), + ] + + operations = [ + migrations.RemoveField( + model_name='blade', + name='topology', + ), + ] diff --git a/geotrek/signage/models.py b/geotrek/signage/models.py index 5fe4d93ef6..023b165f3a 100755 --- a/geotrek/signage/models.py +++ b/geotrek/signage/models.py @@ -315,12 +315,6 @@ class Blade( conditions = models.ManyToManyField( BladeCondition, related_name="blades", verbose_name=_("Condition"), blank=True ) - topology = models.ForeignKey( - Topology, - related_name="blades_set", - verbose_name=_("Blades"), - on_delete=models.CASCADE, - ) colorblade_verbose_name = _("Color") printedelevation_verbose_name = _("Printed elevation") direction_verbose_name = _("Direction") @@ -339,6 +333,7 @@ def zoning_property(self): @classproperty def geomfield(cls): + # TODO: ensure this keeps working return Topology._meta.get_field("geom") def __str__(self): @@ -346,12 +341,6 @@ def __str__(self): signagecode=self.signage.code, bladenumber=self.number ) - def set_topology(self, topology): - self.topology = topology - if not self.is_signage: - msg = "Expecting a signage" - raise ValueError(msg) - @property def conditions_display(self): return ", ".join( @@ -362,20 +351,26 @@ def conditions_display(self): def paths(self): return self.signage.paths.all() - @property - def is_signage(self): - if self.topology: - return self.topology.kind == Signage.KIND - return False + # TODO: deprecate this method instead of removing it? + # @property + # def is_signage(self): + # if self.topology: + # return self.topology.kind == Signage.KIND + # return False @property def geom(self): return self.signage.geom + # TODO @geom.setter def geom(self, value): self._geom = value + @property + def topology(self): + return self.signage.topo_object + @property def signage_display(self): return f'' @@ -434,12 +429,6 @@ def distance(self, to_cls): return settings.TREK_SIGNAGE_INTERSECTION_MARGIN -@receiver(pre_delete, sender=Topology) -def log_cascade_deletion_from_blade_topology(sender, instance, using, **kwargs): - # Blade are deleted when Topology are deleted - log_cascade_deletion(sender, instance, Blade, "topology") - - @receiver(pre_delete, sender=Signage) def log_cascade_deletion_from_blade_signage(sender, instance, using, **kwargs): # Blade are deleted when Signage are deleted diff --git a/geotrek/signage/templates/signage/sql/post_90_defaults.sql b/geotrek/signage/templates/signage/sql/post_90_defaults.sql index 53bc179b97..69b2dad328 100644 --- a/geotrek/signage/templates/signage/sql/post_90_defaults.sql +++ b/geotrek/signage/templates/signage/sql/post_90_defaults.sql @@ -58,7 +58,6 @@ ALTER TABLE signage_bladetype ALTER COLUMN date_update SET DEFAULT now(); -- type -- color -- condition --- topology ALTER TABLE signage_blade ALTER COLUMN date_insert SET DEFAULT now(); ALTER TABLE signage_blade ALTER COLUMN date_update SET DEFAULT now(); diff --git a/geotrek/signage/tests/test_models.py b/geotrek/signage/tests/test_models.py index 3ccb5da618..671736b253 100644 --- a/geotrek/signage/tests/test_models.py +++ b/geotrek/signage/tests/test_models.py @@ -37,12 +37,6 @@ def setUpTestData(cls): if not user: UserFactory(username="__internal__") - def test_set_topology_other_error(self): - blade = BladeFactory.create() - infra = InfrastructureFactory.create() - with self.assertRaisesRegex(ValueError, "Expecting a signage"): - blade.set_topology(infra) - def test_cascading_deletions(self): blade = BladeFactory.create() topo_pk = blade.topology.pk