import logging
import os
from collections import defaultdict
+from pathlib import PurePath
import pathvalidate
from django.conf import settings
from django.template.defaultfilters import slugify
from django.utils import timezone
-
+from documents.models import Document
logger = logging.getLogger("paperless.filehandling")
return new_filename
-def generate_filename(doc, counter=0, append_gpg=True, archive_filename=False):
+def generate_filename(
+ doc: Document,
+ counter=0,
+ append_gpg=True,
+ archive_filename=False,
+):
path = ""
filename_format = settings.FILENAME_FORMAT
replacement_text="-",
)
+ no_value_default = "-none-"
+
if doc.correspondent:
correspondent = pathvalidate.sanitize_filename(
doc.correspondent.name,
replacement_text="-",
)
else:
- correspondent = "-none-"
+ correspondent = no_value_default
if doc.document_type:
document_type = pathvalidate.sanitize_filename(
replacement_text="-",
)
else:
- document_type = "-none-"
+ document_type = no_value_default
if doc.archive_serial_number:
asn = str(doc.archive_serial_number)
else:
- asn = "-none-"
+ asn = no_value_default
+
+ if doc.owner is not None:
+ owner_username_str = str(doc.owner.username)
+ else:
+ owner_username_str = no_value_default
+
+ if doc.original_filename is not None:
+ # No extension
+ original_name = PurePath(doc.original_filename).with_suffix("").name
+ else:
+ original_name = no_value_default
# Convert UTC database datetime to localized date
local_added = timezone.localdate(doc.added)
asn=asn,
tags=tags,
tag_list=tag_list,
+ owner_username=owner_username_str,
+ original_name=original_name,
).strip()
if settings.FILENAME_FORMAT_REMOVE_NONE:
from unittest import mock
from django.conf import settings
+from django.contrib.auth.models import User
from django.db import DatabaseError
from django.test import override_settings
from django.test import TestCase
checksum="2",
)
self.assertEqual(generate_filename(doc), "84/August/Aug/The Title.pdf")
+
+ @override_settings(
+ FILENAME_FORMAT="{owner_username}/{title}",
+ )
+ def test_document_owner_string(self):
+ """
+ GIVEN:
+ - Document with an other
+ - Document without an owner
+ - Filename format string includes owner
+ WHEN:
+ - Filename is generated for each document
+ THEN:
+ - Owned document includes username
+ - Document without owner returns "none"
+ """
+
+ u1 = User.objects.create_user("user1")
+
+ owned_doc = Document.objects.create(
+ title="The Title",
+ mime_type="application/pdf",
+ checksum="2",
+ owner=u1,
+ )
+
+ no_owner_doc = Document.objects.create(
+ title="does matter",
+ mime_type="application/pdf",
+ checksum="3",
+ )
+
+ self.assertEqual(generate_filename(owned_doc), "user1/The Title.pdf")
+ self.assertEqual(generate_filename(no_owner_doc), "none/does matter.pdf")
+
+ @override_settings(
+ FILENAME_FORMAT="{original_name}",
+ )
+ def test_document_original_filename(self):
+ """
+ GIVEN:
+ - Document with an original filename
+ - Document without an original filename
+ - Document which was plain text document
+ - Filename format string includes original filename
+ WHEN:
+ - Filename is generated for each document
+ THEN:
+ - Document with original name uses it, dropping suffix
+ - Document without original name returns "none"
+ - Text document returns extension of .txt
+ - Text document archive returns extension of .pdf
+ - No extensions are doubled
+ """
+ doc_with_original = Document.objects.create(
+ title="does matter",
+ mime_type="application/pdf",
+ checksum="3",
+ original_filename="someepdf.pdf",
+ )
+ tricky_with_original = Document.objects.create(
+ title="does matter",
+ mime_type="application/pdf",
+ checksum="1",
+ original_filename="some pdf with spaces and stuff.pdf",
+ )
+ no_original = Document.objects.create(
+ title="does matter",
+ mime_type="application/pdf",
+ checksum="2",
+ )
+
+ text_doc = Document.objects.create(
+ title="does matter",
+ mime_type="text/plain",
+ checksum="4",
+ original_filename="logs.txt",
+ )
+
+ self.assertEqual(generate_filename(doc_with_original), "someepdf.pdf")
+
+ self.assertEqual(
+ generate_filename(tricky_with_original),
+ "some pdf with spaces and stuff.pdf",
+ )
+
+ self.assertEqual(generate_filename(no_original), "none.pdf")
+
+ self.assertEqual(generate_filename(text_doc), "logs.txt")
+ self.assertEqual(generate_filename(text_doc, archive_filename=True), "logs.pdf")