mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Allow filtering on multiple correspondents, doctypes, storage paths
Preserve 'Not assigned' option Fix default logical operator Update frontend strings Fix radio button name overlaps Use include / exclude with multi-select for OneToOne objects
This commit is contained in:
@@ -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()
|
||||
|
||||
|
@@ -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",
|
||||
),
|
||||
),
|
||||
]
|
@@ -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(
|
||||
|
Reference in New Issue
Block a user