mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Cleanup custom fields from saved views on deletion
This commit is contained in:
parent
4da973f6a5
commit
b3bc5d2ce6
@ -36,6 +36,7 @@ from documents.models import Document
|
|||||||
from documents.models import DocumentType
|
from documents.models import DocumentType
|
||||||
from documents.models import MatchingModel
|
from documents.models import MatchingModel
|
||||||
from documents.models import PaperlessTask
|
from documents.models import PaperlessTask
|
||||||
|
from documents.models import SavedView
|
||||||
from documents.models import Tag
|
from documents.models import Tag
|
||||||
from documents.models import Workflow
|
from documents.models import Workflow
|
||||||
from documents.models import WorkflowAction
|
from documents.models import WorkflowAction
|
||||||
@ -549,6 +550,33 @@ def check_paths_and_prune_custom_fields(sender, instance: CustomField, **kwargs)
|
|||||||
update_filename_and_move_files(sender, cf_instance)
|
update_filename_and_move_files(sender, cf_instance)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(models.signals.post_delete, sender=CustomField)
|
||||||
|
def cleanup_custom_field_deletion(sender, instance: CustomField, **kwargs):
|
||||||
|
"""
|
||||||
|
When a custom field is deleted, ensure no saved views reference it.
|
||||||
|
"""
|
||||||
|
field_identifier = SavedView.DisplayFields.CUSTOM_FIELD % instance.pk
|
||||||
|
# remove field from display_fields of all saved views
|
||||||
|
for view in SavedView.objects.filter(display_fields__isnull=False).distinct():
|
||||||
|
if field_identifier in view.display_fields:
|
||||||
|
logger.debug(
|
||||||
|
f"Removing custom field {instance} from view {view}",
|
||||||
|
)
|
||||||
|
view.display_fields.remove(field_identifier)
|
||||||
|
view.save()
|
||||||
|
|
||||||
|
# remove from sort_field of all saved views
|
||||||
|
views_with_sort_updated = SavedView.objects.filter(
|
||||||
|
sort_field=field_identifier,
|
||||||
|
).update(
|
||||||
|
sort_field=SavedView.DisplayFields.CREATED,
|
||||||
|
)
|
||||||
|
if views_with_sort_updated > 0:
|
||||||
|
logger.debug(
|
||||||
|
f"Removing custom field {instance} from sort field of {views_with_sort_updated} views",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def add_to_index(sender, document, **kwargs):
|
def add_to_index(sender, document, **kwargs):
|
||||||
from documents import index
|
from documents import index
|
||||||
|
|
||||||
|
@ -1925,6 +1925,42 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
def test_saved_view_cleanup_after_custom_field_deletion(self):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- Saved view with custom field in display fields and as sort field
|
||||||
|
WHEN:
|
||||||
|
- Custom field is deleted
|
||||||
|
THEN:
|
||||||
|
- Custom field is removed from display fields and sort field
|
||||||
|
"""
|
||||||
|
custom_field = CustomField.objects.create(
|
||||||
|
name="stringfield",
|
||||||
|
data_type=CustomField.FieldDataType.STRING,
|
||||||
|
)
|
||||||
|
|
||||||
|
view = SavedView.objects.create(
|
||||||
|
owner=self.user,
|
||||||
|
name="test",
|
||||||
|
sort_field=SavedView.DisplayFields.CUSTOM_FIELD % custom_field.id,
|
||||||
|
show_on_dashboard=True,
|
||||||
|
show_in_sidebar=True,
|
||||||
|
display_fields=[
|
||||||
|
SavedView.DisplayFields.TITLE,
|
||||||
|
SavedView.DisplayFields.CREATED,
|
||||||
|
SavedView.DisplayFields.CUSTOM_FIELD % custom_field.id,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_field.delete()
|
||||||
|
|
||||||
|
view.refresh_from_db()
|
||||||
|
self.assertEqual(view.sort_field, SavedView.DisplayFields.CREATED)
|
||||||
|
self.assertEqual(
|
||||||
|
view.display_fields,
|
||||||
|
[str(SavedView.DisplayFields.TITLE), str(SavedView.DisplayFields.CREATED)],
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_logs(self):
|
def test_get_logs(self):
|
||||||
log_data = "test\ntest2\n"
|
log_data = "test\ntest2\n"
|
||||||
with (Path(settings.LOGGING_DIR) / "mail.log").open("w") as f:
|
with (Path(settings.LOGGING_DIR) / "mail.log").open("w") as f:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user