🐛(back) keep info if document has deleted children
With the soft delete feature, relying on the is_leaf method from the treebeard is not accurate anymore. To determine if a node is a leaf, it checks if the number of numchild is equal to 0. But a node can have soft deleted children, then numchild is equal to 0, but it is not a leaf because if we want to add a child we have to look for the last child to compute a correct path. Otherwise we will have an error saying that the path already exists.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.7 on 2025-03-14 14:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0019_alter_user_language_default_to_null"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="has_deleted_children",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -486,6 +486,7 @@ class Document(MP_Node, BaseModel):
|
||||
)
|
||||
deleted_at = models.DateTimeField(null=True, blank=True)
|
||||
ancestors_deleted_at = models.DateTimeField(null=True, blank=True)
|
||||
has_deleted_children = models.BooleanField(default=False)
|
||||
|
||||
_content = None
|
||||
|
||||
@@ -546,6 +547,12 @@ class Document(MP_Node, BaseModel):
|
||||
content_file = ContentFile(bytes_content)
|
||||
default_storage.save(file_key, content_file)
|
||||
|
||||
def is_leaf(self):
|
||||
"""
|
||||
:returns: True if the node is has no children
|
||||
"""
|
||||
return not self.has_deleted_children and self.numchild == 0
|
||||
|
||||
@property
|
||||
def key_base(self):
|
||||
"""Key base of the location where the document is stored in object storage."""
|
||||
@@ -903,7 +910,8 @@ class Document(MP_Node, BaseModel):
|
||||
|
||||
if self.depth > 1:
|
||||
self._meta.model.objects.filter(pk=self.get_parent().pk).update(
|
||||
numchild=models.F("numchild") - 1
|
||||
numchild=models.F("numchild") - 1,
|
||||
has_deleted_children=True,
|
||||
)
|
||||
|
||||
# Mark all descendants as soft deleted
|
||||
|
||||
@@ -1297,3 +1297,47 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries):
|
||||
def test_models_documents_get_select_options(ancestors_links, select_options):
|
||||
"""Validate that the "get_select_options" method operates as expected."""
|
||||
assert models.LinkReachChoices.get_select_options(ancestors_links) == select_options
|
||||
|
||||
|
||||
def test_models_documents_children_create_after_sibling_deletion():
|
||||
"""
|
||||
It should be possible to create a new child after all children have been deleted.
|
||||
"""
|
||||
|
||||
root = factories.DocumentFactory()
|
||||
assert root.numchild == 0
|
||||
assert root.has_deleted_children is False
|
||||
assert root.is_leaf() is True
|
||||
child1 = factories.DocumentFactory(parent=root)
|
||||
child2 = factories.DocumentFactory(parent=root)
|
||||
|
||||
root.refresh_from_db()
|
||||
assert root.numchild == 2
|
||||
assert root.has_deleted_children is False
|
||||
assert root.is_leaf() is False
|
||||
|
||||
child1.soft_delete()
|
||||
child2.soft_delete()
|
||||
root.refresh_from_db()
|
||||
assert root.numchild == 0
|
||||
assert root.has_deleted_children is True
|
||||
assert root.is_leaf() is False
|
||||
|
||||
factories.DocumentFactory(parent=root)
|
||||
root.refresh_from_db()
|
||||
assert root.numchild == 1
|
||||
assert root.has_deleted_children is True
|
||||
assert root.is_leaf() is False
|
||||
|
||||
|
||||
def test_models_documents_has_deleted_children():
|
||||
"""
|
||||
A document should have its has_deleted_children attribute set to True if one of its children
|
||||
has been solf deleted no matter if numchild is 0 or not.
|
||||
"""
|
||||
root = factories.DocumentFactory()
|
||||
child = factories.DocumentFactory(parent=root)
|
||||
assert root.has_deleted_children is False
|
||||
child.soft_delete()
|
||||
root.refresh_from_db()
|
||||
assert root.has_deleted_children is True
|
||||
|
||||
Reference in New Issue
Block a user