Use a custom filter to work around access to fields with spaces
This commit is contained in:
parent
6d8ffa3382
commit
dc25d53af4
@ -438,6 +438,10 @@ with more complex logic.
|
|||||||
- `{{ tag_name_list }}`: A list of tag names applied to the document, ordered by the tag name. Note this is a list, not a single string
|
- `{{ tag_name_list }}`: A list of tag names applied to the document, ordered by the tag name. Note this is a list, not a single string
|
||||||
- `{{ custom_fields }}`: A mapping of custom field names to their type and value. A user can access the mapping by field name or check if a field is applied by checking its existence in the variable.
|
- `{{ custom_fields }}`: A mapping of custom field names to their type and value. A user can access the mapping by field name or check if a field is applied by checking its existence in the variable.
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
To access a custom field which has a space in the name, use the `get_cf_value` filter. See the examples below.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
This example will construct a path based on the archive serial number range:
|
This example will construct a path based on the archive serial number range:
|
||||||
@ -486,6 +490,12 @@ To use custom fields:
|
|||||||
If the document has a custom field named "Invoice" with a value of 123, it would be filed into the `invoices/123.pdf`, but a document without the custom field
|
If the document has a custom field named "Invoice" with a value of 123, it would be filed into the `invoices/123.pdf`, but a document without the custom field
|
||||||
would be filed to `not-invoices/Title.pdf`
|
would be filed to `not-invoices/Title.pdf`
|
||||||
|
|
||||||
|
If the custom field is named "Invoice Number", you would access the value of it via the `get_cf_value` filter due to quirks of the Django Template Language:
|
||||||
|
|
||||||
|
```django
|
||||||
|
"invoices/{{ custom_fields|get_cf_value:'Invoice Number' }}"
|
||||||
|
```
|
||||||
|
|
||||||
## Automatic recovery of invalid PDFs {#pdf-recovery}
|
## Automatic recovery of invalid PDFs {#pdf-recovery}
|
||||||
|
|
||||||
Paperless will attempt to "clean" certain invalid PDFs with `qpdf` before processing if, for example, the mime_type
|
Paperless will attempt to "clean" certain invalid PDFs with `qpdf` before processing if, for example, the mime_type
|
||||||
|
@ -26,7 +26,10 @@ INVALID_VARIABLE_STR = "InvalidVarError"
|
|||||||
filepath_engine = Engine(
|
filepath_engine = Engine(
|
||||||
autoescape=False,
|
autoescape=False,
|
||||||
string_if_invalid=f"{INVALID_VARIABLE_STR}: %s",
|
string_if_invalid=f"{INVALID_VARIABLE_STR}: %s",
|
||||||
libraries={"filepath": "documents.templatetags.filepath"},
|
libraries={
|
||||||
|
"filepath": "documents.templatetags.filepath",
|
||||||
|
"get_cf_value": "documents.templatetags.get_cf_value",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -330,7 +333,9 @@ def validate_template_and_render(
|
|||||||
try:
|
try:
|
||||||
# We load the custom tag used to remove spaces and newlines from the final string around the user string
|
# We load the custom tag used to remove spaces and newlines from the final string around the user string
|
||||||
template = filepath_engine.from_string(
|
template = filepath_engine.from_string(
|
||||||
"{% load filepath %}{% filepath %}" + template_string + "{% endfilepath %}",
|
"{% load filepath %}{% load get_cf_value %}{% filepath %}"
|
||||||
|
+ template_string
|
||||||
|
+ "{% endfilepath %}",
|
||||||
)
|
)
|
||||||
rendered_template = template.render(Context(context))
|
rendered_template = template.render(Context(context))
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ from documents.models import WorkflowTrigger
|
|||||||
from documents.parsers import is_mime_type_supported
|
from documents.parsers import is_mime_type_supported
|
||||||
from documents.permissions import get_groups_with_only_permission
|
from documents.permissions import get_groups_with_only_permission
|
||||||
from documents.permissions import set_permissions_for_object
|
from documents.permissions import set_permissions_for_object
|
||||||
from documents.templatetags import convert_to_django_template_format
|
from documents.templatetags.filepath import convert_to_django_template_format
|
||||||
from documents.validators import uri_validator
|
from documents.validators import uri_validator
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.serializers")
|
logger = logging.getLogger("paperless.serializers")
|
||||||
|
12
src/documents/templatetags/get_cf_value.py
Normal file
12
src/documents/templatetags/get_cf_value.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter("get_cf_value")
|
||||||
|
def get_cf_value(custom_field_data: dict[str, dict[str, str]], name: str):
|
||||||
|
"""
|
||||||
|
See https://stackoverflow.com/questions/2970244/django-templates-value-of-dictionary-key-with-a-space-in-it/2970337#2970337
|
||||||
|
"""
|
||||||
|
data = custom_field_data[name]["value"]
|
||||||
|
return data
|
@ -1245,17 +1245,6 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_template_with_custom_fields(self):
|
def test_template_with_custom_fields(self):
|
||||||
sp = StoragePath.objects.create(
|
|
||||||
name="sp1",
|
|
||||||
path="""
|
|
||||||
{% if "Invoice" in custom_fields %}
|
|
||||||
invoices/{{ custom_fields.Invoice.value }}
|
|
||||||
{% else %}
|
|
||||||
not-invoices/{{ title }}
|
|
||||||
{% endif %}
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
|
|
||||||
doc_a = Document.objects.create(
|
doc_a = Document.objects.create(
|
||||||
title="Some Title",
|
title="Some Title",
|
||||||
created=timezone.make_aware(datetime.datetime(2020, 6, 25, 7, 36, 51, 153)),
|
created=timezone.make_aware(datetime.datetime(2020, 6, 25, 7, 36, 51, 153)),
|
||||||
@ -1264,7 +1253,6 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
|
|||||||
pk=2,
|
pk=2,
|
||||||
checksum="2",
|
checksum="2",
|
||||||
archive_serial_number=25,
|
archive_serial_number=25,
|
||||||
storage_path=sp,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cf = CustomField.objects.create(
|
cf = CustomField.objects.create(
|
||||||
@ -1278,17 +1266,32 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
|
|||||||
value_int=1234,
|
value_int=1234,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
with override_settings(
|
||||||
generate_filename(doc_a),
|
FILENAME_FORMAT="""
|
||||||
"invoices/1234.pdf",
|
{% if "Invoice" in custom_fields %}
|
||||||
)
|
invoices/{{ custom_fields|get_cf_value:'Invoice' }}
|
||||||
|
{% else %}
|
||||||
|
not-invoices/{{ title }}
|
||||||
|
{% endif %}
|
||||||
|
""",
|
||||||
|
):
|
||||||
|
self.assertEqual(
|
||||||
|
generate_filename(doc_a),
|
||||||
|
"invoices/1234.pdf",
|
||||||
|
)
|
||||||
|
|
||||||
cfi.delete()
|
cf.name = "Invoice Number"
|
||||||
|
cfi.value_int = 4567
|
||||||
|
cfi.save()
|
||||||
|
cf.save()
|
||||||
|
|
||||||
self.assertEqual(
|
with override_settings(
|
||||||
generate_filename(doc_a),
|
FILENAME_FORMAT="invoices/{{ custom_fields|get_cf_value:'Invoice Number' }}",
|
||||||
"not-invoices/Some Title.pdf",
|
):
|
||||||
)
|
self.assertEqual(
|
||||||
|
generate_filename(doc_a),
|
||||||
|
"invoices/4567.pdf",
|
||||||
|
)
|
||||||
|
|
||||||
def test_using_other_filters(self):
|
def test_using_other_filters(self):
|
||||||
doc_a = Document.objects.create(
|
doc_a = Document.objects.create(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user