Delete Stale Edges when removing a Node from a Pathway (#41)

Co-authored-by: Tim Lorsbach <tim@lorsba.ch>
Reviewed-on: enviPath/enviPy#41
This commit is contained in:
2025-07-31 07:50:50 +12:00
parent a1aebfa54d
commit c9d6d8b024
4 changed files with 38 additions and 9 deletions

View File

@ -4,3 +4,6 @@ from django.apps import AppConfig
class EPDBConfig(AppConfig): class EPDBConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'epdb' name = 'epdb'
def ready(self):
import epdb.signals # noqa: F401

View File

@ -1044,7 +1044,7 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin):
return IndigoUtils.mol_to_svg(self.default_node_label.smiles) return IndigoUtils.mol_to_svg(self.default_node_label.smiles)
class Edge(PolymorphicModel, EnviPathModel, AliasMixin, ScenarioMixin): class Edge(EnviPathModel, AliasMixin, ScenarioMixin):
pathway = models.ForeignKey('epdb.Pathway', verbose_name='belongs to', on_delete=models.CASCADE, db_index=True) pathway = models.ForeignKey('epdb.Pathway', verbose_name='belongs to', on_delete=models.CASCADE, db_index=True)
edge_label = models.ForeignKey('epdb.Reaction', verbose_name='Edge label', null=True, on_delete=models.SET_NULL) edge_label = models.ForeignKey('epdb.Reaction', verbose_name='Edge label', null=True, on_delete=models.SET_NULL)
start_nodes = models.ManyToManyField('epdb.Node', verbose_name='Start Nodes', related_name='edge_educts') start_nodes = models.ManyToManyField('epdb.Node', verbose_name='Start Nodes', related_name='edge_educts')

20
epdb/signals.py Normal file
View File

@ -0,0 +1,20 @@
from django.db import transaction
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from epdb.models import Node, Edge
@receiver(pre_delete, sender=Node)
@transaction.atomic
def delete_orphan_edges(sender, instance, **kwargs):
# check if the node that is about to be deleted is the only start node
for edge in Edge.objects.filter(start_nodes=instance):
if edge.start_nodes.count() == 1:
edge.delete()
# same for end_nodes
for edge in Edge.objects.filter(end_nodes=instance):
# check if the node that is about to be deleted is the only start node
if edge.end_nodes.count() == 1:
edge.delete()

View File

@ -1417,15 +1417,20 @@ def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
return render(request, 'objects/node.html', context) return render(request, 'objects/node.html', context)
elif request.method == 'POST': elif request.method == 'POST':
if s.DEBUG:
for k, v in request.POST.items(): log_post_params(request)
print(k, v)
if hidden := request.POST.get('hidden', None): if hidden := request.POST.get('hidden', None):
if hidden == 'delete-node': if hidden == 'delete-node':
current_node.delete()
return redirect(current_pathway.url)
# pre_delete signal will take care of edge deletion
current_node.delete()
return redirect(current_pathway.url)
else:
return HttpResponseBadRequest()
else:
return HttpResponseBadRequest()
else: else:
return HttpResponseNotAllowed(['GET', 'POST']) return HttpResponseNotAllowed(['GET', 'POST'])
@ -1474,6 +1479,8 @@ def package_pathway_edges(request, package_uuid, pathway_uuid):
elif request.method == 'POST': elif request.method == 'POST':
log_post_params(request)
edge_name = request.POST.get('edge-name') edge_name = request.POST.get('edge-name')
edge_description = request.POST.get('edge-description') edge_description = request.POST.get('edge-description')
edge_substrates = request.POST.getlist('edge-substrates') edge_substrates = request.POST.getlist('edge-substrates')
@ -1517,9 +1524,8 @@ def package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
return render(request, 'objects/edge.html', context) return render(request, 'objects/edge.html', context)
elif request.method == 'POST': elif request.method == 'POST':
if s.DEBUG:
for k, v in request.POST.items(): log_post_params(request)
print(k, v)
if hidden := request.POST.get('hidden', None): if hidden := request.POST.get('hidden', None):
if hidden == 'delete-edge': if hidden == 'delete-edge':