Merge pull request #2893 from paperless-ngx/feature-enhanced-object-filtering

Enhancement: support filtering multiple correspondents, doctypes & storage paths
This commit is contained in:
shamoon
2023-03-17 18:46:22 -07:00
committed by GitHub
20 changed files with 752 additions and 130 deletions

View File

@@ -36,29 +36,30 @@ class DocumentTypeFilterSet(FilterSet):
fields = {"name": CHAR_KWARGS}
class TagsFilter(Filter):
def __init__(self, exclude=False, in_list=False):
class ObjectFilter(Filter):
def __init__(self, exclude=False, in_list=False, field_name=""):
super().__init__()
self.exclude = exclude
self.in_list = in_list
self.field_name = field_name
def filter(self, qs, value):
if not value:
return qs
try:
tag_ids = [int(x) for x in value.split(",")]
object_ids = [int(x) for x in value.split(",")]
except ValueError:
return qs
if self.in_list:
qs = qs.filter(tags__id__in=tag_ids).distinct()
qs = qs.filter(**{f"{self.field_name}__id__in": object_ids}).distinct()
else:
for tag_id in tag_ids:
for obj_id in object_ids:
if self.exclude:
qs = qs.exclude(tags__id=tag_id)
qs = qs.exclude(**{f"{self.field_name}__id": obj_id})
else:
qs = qs.filter(tags__id=tag_id)
qs = qs.filter(**{f"{self.field_name}__id": obj_id})
return qs
@@ -90,11 +91,17 @@ class DocumentFilterSet(FilterSet):
exclude=True,
)
tags__id__all = TagsFilter()
tags__id__all = ObjectFilter(field_name="tags")
tags__id__none = TagsFilter(exclude=True)
tags__id__none = ObjectFilter(field_name="tags", exclude=True)
tags__id__in = TagsFilter(in_list=True)
tags__id__in = ObjectFilter(field_name="tags", in_list=True)
correspondent__id__none = ObjectFilter(field_name="correspondent", exclude=True)
document_type__id__none = ObjectFilter(field_name="document_type", exclude=True)
storage_path__id__none = ObjectFilter(field_name="storage_path", exclude=True)
is_in_inbox = InboxFilter()

View File

@@ -0,0 +1,54 @@
# Generated by Django 4.1.5 on 2023-03-15 07:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("documents", "1033_alter_documenttype_options_alter_tag_options_and_more"),
]
operations = [
migrations.AlterField(
model_name="savedviewfilterrule",
name="rule_type",
field=models.PositiveIntegerField(
choices=[
(0, "title contains"),
(1, "content contains"),
(2, "ASN is"),
(3, "correspondent is"),
(4, "document type is"),
(5, "is in inbox"),
(6, "has tag"),
(7, "has any tag"),
(8, "created before"),
(9, "created after"),
(10, "created year is"),
(11, "created month is"),
(12, "created day is"),
(13, "added before"),
(14, "added after"),
(15, "modified before"),
(16, "modified after"),
(17, "does not have tag"),
(18, "does not have ASN"),
(19, "title or content contains"),
(20, "fulltext query"),
(21, "more like this"),
(22, "has tags in"),
(23, "ASN greater than"),
(24, "ASN less than"),
(25, "storage path is"),
(26, "has correspondent in"),
(27, "does not have correspondent in"),
(28, "has document type in"),
(29, "does not have document type in"),
(30, "has storage path in"),
(31, "does not have storage path in"),
],
verbose_name="rule type",
),
),
]

View File

@@ -447,6 +447,12 @@ class SavedViewFilterRule(models.Model):
(23, _("ASN greater than")),
(24, _("ASN less than")),
(25, _("storage path is")),
(26, _("has correspondent in")),
(27, _("does not have correspondent in")),
(28, _("has document type in")),
(29, _("does not have document type in")),
(30, _("has storage path in")),
(31, _("does not have storage path in")),
]
saved_view = models.ForeignKey(