Skip to content

Commit dce101b

Browse files
committed
Fix include/exclude multi filter to use Exist subquery
1 parent af9000a commit dce101b

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

froide/account/admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ class TaggedUserAdmin(admin.ModelAdmin):
6565
class UserTagListFilter(MultiFilterMixin, TaggitListFilter):
6666
tag_class = TaggedUser
6767
title = "Tags"
68-
parameter_name = "tags__slug"
68+
parameter_name = "tag__slug"
6969
lookup_name = "__in"
70+
related_model = TaggedUser
71+
related_model_fk_field = "content_object"
7072

7173

7274
class AddToGroupForm(forms.Form):

froide/foirequest/admin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,10 @@ class DeliveryStatusInline(admin.TabularInline):
523523
class MessageTagsFilter(MultiFilterMixin, TaggitListFilter):
524524
tag_class = TaggedMessage
525525
title = "Tags"
526-
parameter_name = "tags__slug"
526+
parameter_name = "tag__slug"
527527
lookup_name = "__in"
528+
related_model = TaggedMessage
529+
related_model_fk_field = "content_object"
528530

529531

530532
@admin.register(FoiMessage)
@@ -610,6 +612,7 @@ def get_urls(self):
610612

611613
def get_queryset(self, request):
612614
qs = super().get_queryset(request)
615+
qs = qs.select_related("request")
613616
qs = qs.prefetch_related("deliverystatus")
614617
return qs
615618

froide/helper/admin_utils.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ def create_used_parameters(self):
317317
class MultiFilterMixin:
318318
template = "helper/admin/multi_filter.html"
319319
lookup_name = ""
320+
related_model = None
321+
related_model_fk_field = None
320322

321323
def queryset(self, request, queryset):
322324
if request.GET.get(self.parameter_name):
@@ -329,12 +331,25 @@ def queryset(self, request, queryset):
329331
def get_q(cls, values, lookup):
330332
includes = [v for v in values if not v.startswith("~")]
331333
excludes = [v[1:] for v in values if v.startswith("~")]
334+
335+
if not lookup.endswith("__in"):
336+
lookup += "__in"
337+
338+
def exists(values):
339+
return models.Exists(
340+
cls.related_model.objects.filter(
341+
**{
342+
cls.related_model_fk_field: models.OuterRef("id"),
343+
lookup: values,
344+
}
345+
)
346+
)
347+
332348
q = models.Q()
333349
if includes:
334-
for inc in includes:
335-
q |= models.Q(**{lookup: [inc]})
350+
q &= exists(includes)
336351
if excludes:
337-
q &= ~models.Q(**{lookup: excludes})
352+
q &= ~exists(excludes)
338353
return q
339354

340355
def value_as_list(self):

0 commit comments

Comments
 (0)