Compare commits

...

1 Commits

Author SHA1 Message Date
shamoon
05beea9215 Fix: support string coercion in filepath jinja templates 2026-03-04 07:25:06 -08:00
2 changed files with 65 additions and 6 deletions

View File

@@ -79,6 +79,23 @@ class PlaceholderString(str):
NO_VALUE_PLACEHOLDER = PlaceholderString("-none-")
class MatchingModelContext:
"""
Safe template context for related objects.
Keeps legacy behavior where including the object ina template yields the related object's
name as a string, while still exposing limited attributes.
"""
def __init__(self, *, id: int, name: str, path: str | None = None):
self.id = id
self.name = name
self.path = path
def __str__(self) -> str:
return self.name
_template_environment.undefined = _LogStrictUndefined
_template_environment.filters["get_cf_value"] = get_cf_value
@@ -221,19 +238,26 @@ def get_safe_document_context(
else None,
"tags": [{"name": tag.name, "id": tag.id} for tag in tags],
"correspondent": (
{"name": document.correspondent.name, "id": document.correspondent.id}
MatchingModelContext(
name=document.correspondent.name,
id=document.correspondent.id,
)
if document.correspondent
else None
),
"document_type": (
{"name": document.document_type.name, "id": document.document_type.id}
MatchingModelContext(
name=document.document_type.name,
id=document.document_type.id,
)
if document.document_type
else None
),
"storage_path": {
"path": document.storage_path.path,
"id": document.storage_path.id,
}
"storage_path": MatchingModelContext(
name=document.storage_path.name,
path=document.storage_path.path,
id=document.storage_path.id,
)
if document.storage_path
else None,
}

View File

@@ -1341,6 +1341,41 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
Path("somepath/asn-201-400/asn-3xx/Does Matter.pdf"),
)
def test_template_related_context_keeps_legacy_string_coercion(self):
"""
GIVEN:
- A storage path template that uses related objects directly as strings
WHEN:
- Filepath for a document with this format is called
THEN:
- Related objects coerce to their names (legacy behavior)
- Explicit attribute access remains available for new templates
"""
sp = StoragePath.objects.create(
name="PARTNER",
path=(
"{{ document.storage_path|lower }} / "
"{{ document.correspondent|lower|replace('mi:', 'mieter/') }} / "
"{{ document_type|lower }} / "
"{{ title|lower }}"
),
)
doc = Document.objects.create(
title="scan_017562",
created=datetime.date(2025, 7, 2),
added=timezone.make_aware(datetime.datetime(2026, 3, 3, 11, 53, 16)),
mime_type="application/pdf",
checksum="test-checksum",
storage_path=sp,
correspondent=Correspondent.objects.create(name="mi:kochkach"),
document_type=DocumentType.objects.create(name="Mietvertrag"),
)
self.assertEqual(
generate_filename(doc),
Path("partner/mieter/kochkach/mietvertrag/scan_017562.pdf"),
)
@override_settings(
FILENAME_FORMAT="{{creation_date}}/{{ title_name_str }}",
)