diff --git a/src/documents/admin.py b/src/documents/admin.py index 60245dd35..ff6abda2f 100644 --- a/src/documents/admin.py +++ b/src/documents/admin.py @@ -13,11 +13,13 @@ from django.utils.safestring import mark_safe from djangoql.admin import DjangoQLSearchMixin -from documents.actions import (add_tag_to_selected, - remove_correspondent_from_selected, - remove_tag_from_selected, - set_correspondent_on_selected) -from paperless.utils import slugify +from documents.actions import ( + add_tag_to_selected, + remove_correspondent_from_selected, + remove_tag_from_selected, + set_correspondent_on_selected +) +from paperless.utils import make_searchable from .models import Correspondent, Document, Log, Tag @@ -176,7 +178,7 @@ class Media: "correspondent__name", "searchable_title", "searchable_content", - "tags__name", + "tags__searchable_name", ) readonly_fields = ("added", "file_type", "storage_type",) list_display = ("title", "created", "added", "thumbnail", "correspondent", diff --git a/src/documents/migrations/0023_document_searchable_content.py b/src/documents/migrations/0023_document_searchable_content.py index f314c235b..662f2c6fe 100644 --- a/src/documents/migrations/0023_document_searchable_content.py +++ b/src/documents/migrations/0023_document_searchable_content.py @@ -3,7 +3,13 @@ from django.db import migrations, models -from paperless.utils import slugify as slugifyOCR + +def slugifyOCR(content): + return ( + unicodedata.normalize("NFKD", content.casefold()) + .encode("ASCII", "ignore") + .decode("utf-8") + ) class Migration(migrations.Migration): @@ -20,12 +26,16 @@ def casefold_forwards(apps, schema_editor): doc.searchable_content = slugifyOCR(doc.content) doc.save() - def casefold_backwards(apps, schema_editor): - pass + Tag = apps.get_model("documents", "Tag") + + for tag in Tag.objects.all(): + tag.searchable_name = slugifyOCR(tag.name) + tag.save() def database_backwards(self, app_label, schema_editor, from_state, to_state): migrations.RemoveField(model_name="document", name="searchable_content"), migrations.RemoveField(model_name="document", name="searchable_title"), + migrations.RemoveField(model_name="tag", name="searchable_name"), operations = [ migrations.AddField( @@ -40,5 +50,12 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state): max_length=128, blank=True, db_index=True, editable=False ), ), - migrations.RunPython(casefold_forwards, casefold_backwards), + migrations.AddField( + model_name="tag", + name="searchable_name", + field=models.CharField( + max_length=128, blank=True, db_index=True, editable=False + ), + ), + migrations.RunPython(casefold_forwards, migrations.RunPython.noop), ] diff --git a/src/documents/models.py b/src/documents/models.py index 267e8db28..1d5fcb3b4 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -9,12 +9,11 @@ import dateutil.parser from django.conf import settings from django.db import models -from django.template.defaultfilters import slugify from django.utils import timezone from django.utils.text import slugify from fuzzywuzzy import fuzz -from paperless.utils import slugify as slugifyOCR +from paperless.utils import make_searchable from .managers import LogManager @@ -185,6 +184,15 @@ class Tag(MatchingModel): colour = models.PositiveIntegerField(choices=COLOURS, default=1) + searchable_name = models.CharField( + max_length=128, blank=True, db_index=True, editable=False, + ) + + def save(self, *args, **kwargs): + if self.name is not None: + self.searchable_name = make_searchable(self.name) + return super().save(*args, **kwargs) + class Document(models.Model): @@ -283,9 +291,9 @@ def __str__(self): def save(self, *args, **kwargs): if self.title is not None: - self.searchable_title = slugifyOCR(self.title) + self.searchable_title = make_searchable(self.title) if self.content is not None: - self.searchable_content = slugifyOCR(self.content) + self.searchable_content = make_searchable(self.content) return super().save(*args, **kwargs) @property diff --git a/src/documents/tests/test_tag_model.py b/src/documents/tests/test_tag_model.py new file mode 100644 index 000000000..76a1602a3 --- /dev/null +++ b/src/documents/tests/test_tag_model.py @@ -0,0 +1,12 @@ +from unittest import mock + +from django.test import TestCase + +from ..models import Tag + + +class TestTag(TestCase): + def test_searchable_name(self): + tag = Tag.objects.create(name="Titlé") + self.assertEqual(tag.name, "Titlé") + self.assertEqual(tag.searchable_name, "title") diff --git a/src/paperless/utils.py b/src/paperless/utils.py index a687f77ed..5b90f5fe8 100644 --- a/src/paperless/utils.py +++ b/src/paperless/utils.py @@ -1,7 +1,7 @@ import unicodedata -def slugify(content): +def make_searchable(content): return ( unicodedata.normalize("NFKD", content.casefold()) .encode("ASCII", "ignore")