mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	When a StoragePath is changed, check if related documents require a rename
This commit is contained in:
		@@ -414,13 +414,6 @@ structure as in the previous example above.
 | 
			
		||||
    Defining a storage path is optional. If no storage path is defined for a
 | 
			
		||||
    document, the global `PAPERLESS_FILENAME_FORMAT` is applied.
 | 
			
		||||
 | 
			
		||||
!!! warning
 | 
			
		||||
 | 
			
		||||
    If you adjust the format of an existing storage path, old documents
 | 
			
		||||
    don't get relocated automatically. You need to run the
 | 
			
		||||
    [document renamer](/administration#renamer) to
 | 
			
		||||
    adjust their paths.
 | 
			
		||||
 | 
			
		||||
## Celery Monitoring {#celery-monitoring}
 | 
			
		||||
 | 
			
		||||
The monitoring tool
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ from ..file_handling import generate_unique_filename
 | 
			
		||||
from ..models import Document
 | 
			
		||||
from ..models import MatchingModel
 | 
			
		||||
from ..models import PaperlessTask
 | 
			
		||||
from ..models import StoragePath
 | 
			
		||||
from ..models import Tag
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger("paperless.handlers")
 | 
			
		||||
@@ -495,6 +496,16 @@ def update_filename_and_move_files(sender, instance, **kwargs):
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@receiver(models.signals.post_save, sender=StoragePath)
 | 
			
		||||
def update_document_storage_path(sender, instance, **kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Triggers when a storage path is changed, running against any documents using
 | 
			
		||||
    the path, and checks to see if they need to be renamed
 | 
			
		||||
    """
 | 
			
		||||
    for document in instance.documents.all():
 | 
			
		||||
        update_filename_and_move_files(None, document)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def set_log_entry(sender, document=None, logging_group=None, **kwargs):
 | 
			
		||||
 | 
			
		||||
    ct = ContentType.objects.get(model="document")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
import datetime
 | 
			
		||||
import hashlib
 | 
			
		||||
import os
 | 
			
		||||
import random
 | 
			
		||||
import tempfile
 | 
			
		||||
import uuid
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from unittest import mock
 | 
			
		||||
 | 
			
		||||
@@ -16,7 +13,6 @@ from django.utils import timezone
 | 
			
		||||
from ..file_handling import create_source_path_directory
 | 
			
		||||
from ..file_handling import delete_empty_directories
 | 
			
		||||
from ..file_handling import generate_filename
 | 
			
		||||
from ..file_handling import generate_unique_filename
 | 
			
		||||
from ..models import Correspondent
 | 
			
		||||
from ..models import Document
 | 
			
		||||
from ..models import DocumentType
 | 
			
		||||
@@ -871,7 +867,7 @@ class TestFileHandlingWithArchive(DirectoriesMixin, TestCase):
 | 
			
		||||
        self.assertTrue(os.path.isfile(doc.archive_path))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestFilenameGeneration(TestCase):
 | 
			
		||||
class TestFilenameGeneration(DirectoriesMixin, TestCase):
 | 
			
		||||
    @override_settings(FILENAME_FORMAT="{title}")
 | 
			
		||||
    def test_invalid_characters(self):
 | 
			
		||||
 | 
			
		||||
@@ -1036,6 +1032,47 @@ class TestFilenameGeneration(TestCase):
 | 
			
		||||
        self.assertEqual(generate_filename(doc_a), "0000002.pdf")
 | 
			
		||||
        self.assertEqual(generate_filename(doc_b), "SomeImportantNone/2020-07-25.pdf")
 | 
			
		||||
 | 
			
		||||
    def test_document_storage_path_changed(self):
 | 
			
		||||
        """
 | 
			
		||||
        GIVEN:
 | 
			
		||||
            - Document with a defined storage path
 | 
			
		||||
        WHEN:
 | 
			
		||||
            - The storage path format is updated
 | 
			
		||||
        THEN:
 | 
			
		||||
            - Document is renamed to the new format
 | 
			
		||||
        """
 | 
			
		||||
        sp = StoragePath.objects.create(path="TestFolder/{created}")
 | 
			
		||||
        document = Document.objects.create(
 | 
			
		||||
            mime_type="application/pdf",
 | 
			
		||||
            created=timezone.make_aware(datetime.datetime(2020, 6, 25, 7, 36, 51, 153)),
 | 
			
		||||
            storage_path=sp,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Ensure that filename is properly generated
 | 
			
		||||
        document.filename = generate_filename(document)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            document.source_path,
 | 
			
		||||
            os.path.join(settings.ORIGINALS_DIR, "TestFolder/2020-06-25.pdf"),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Actually create the file
 | 
			
		||||
        create_source_path_directory(document.source_path)
 | 
			
		||||
        Path(document.source_path).touch()
 | 
			
		||||
        self.assertTrue(os.path.isfile(document.source_path))
 | 
			
		||||
        document.save()
 | 
			
		||||
 | 
			
		||||
        # Change format
 | 
			
		||||
        sp.path = "NewFolder/{created}"
 | 
			
		||||
        sp.save()
 | 
			
		||||
 | 
			
		||||
        document.refresh_from_db()
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            document.source_path,
 | 
			
		||||
            os.path.join(settings.ORIGINALS_DIR, "NewFolder/2020-06-25.pdf"),
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(os.path.isfile(document.source_path))
 | 
			
		||||
 | 
			
		||||
    @override_settings(
 | 
			
		||||
        FILENAME_FORMAT="{created_year_short}/{created_month_name_short}/{created_month_name}/{title}",
 | 
			
		||||
    )
 | 
			
		||||
@@ -1063,28 +1100,3 @@ class TestFilenameGeneration(TestCase):
 | 
			
		||||
            checksum="2",
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(generate_filename(doc), "84/August/Aug/The Title.pdf")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run():
 | 
			
		||||
    doc = Document.objects.create(
 | 
			
		||||
        checksum=str(uuid.uuid4()),
 | 
			
		||||
        title=str(uuid.uuid4()),
 | 
			
		||||
        content="wow",
 | 
			
		||||
    )
 | 
			
		||||
    doc.filename = generate_unique_filename(doc)
 | 
			
		||||
    Path(doc.thumbnail_path).touch()
 | 
			
		||||
    with open(doc.source_path, "w") as f:
 | 
			
		||||
        f.write(str(uuid.uuid4()))
 | 
			
		||||
    with open(doc.source_path, "rb") as f:
 | 
			
		||||
        doc.checksum = hashlib.md5(f.read()).hexdigest()
 | 
			
		||||
 | 
			
		||||
    with open(doc.archive_path, "w") as f:
 | 
			
		||||
        f.write(str(uuid.uuid4()))
 | 
			
		||||
    with open(doc.archive_path, "rb") as f:
 | 
			
		||||
        doc.archive_checksum = hashlib.md5(f.read()).hexdigest()
 | 
			
		||||
 | 
			
		||||
    doc.save()
 | 
			
		||||
 | 
			
		||||
    for i in range(30):
 | 
			
		||||
        doc.title = str(random.randrange(1, 5))
 | 
			
		||||
        doc.save()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user