[PATCH 1/2] REST: Resolve performance issues with '/events' web view

Stephen Finucane stephen at that.guru
Fri May 11 00:45:05 AEST 2018

The dropdown select-based filters in the web view of the REST API have
stung us a few times. In this case, populating these filters for the
'/events' endpoint results in a huge query that hammers the database and
results in seriously laggy responses.

The root cause of this performance issues was erroneously identified as
an issue with the JSON renderer so that particular patch can now be
reverted. This will be done separately.

Signed-off-by: Stephen Finucane <stephen at that.guru>
Cc: Daniel Axtens <dja at axtens.net>
We might want to look at extending this to other endpoint, which are
probably seeing similar issues (albeit, not as severe). I haven't done
this yet though, out of fear of engaging in premature optimization [1].

[1] https://xkcd.com/1691/
 patchwork/api/filters.py | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py
index f6fff792..7e818954 100644
--- a/patchwork/api/filters.py
+++ b/patchwork/api/filters.py
@@ -24,6 +24,7 @@ from django_filters.rest_framework import FilterSet
 from django_filters import IsoDateTimeFilter
 from django_filters import ModelMultipleChoiceFilter
 from django.forms import ModelMultipleChoiceField as BaseMultipleChoiceField
+from django.forms.widgets import MultipleHiddenInput
 from patchwork.models import Bundle
 from patchwork.models import Check
@@ -200,10 +201,17 @@ class CheckFilterSet(TimestampMixin, FilterSet):
 class EventFilterSet(TimestampMixin, FilterSet):
-    project = ProjectFilter(queryset=Project.objects.all())
-    series = BaseFilter(queryset=Series.objects.all())
-    patch = BaseFilter(queryset=Patch.objects.all())
-    cover = BaseFilter(queryset=CoverLetter.objects.all())
+    # NOTE(stephenfin): We disable the select-based HTML widgets for these
+    # filters as the resulting query is _huge_
+    # TODO(stephenfin): We should really use an AJAX widget of some form here
+    project = ProjectFilter(queryset=Project.objects.all(),
+                            widget=MultipleHiddenInput)
+    series = BaseFilter(queryset=Series.objects.all(),
+                        widget=MultipleHiddenInput)
+    patch = BaseFilter(queryset=Patch.objects.all(),
+                       widget=MultipleHiddenInput)
+    cover = BaseFilter(queryset=CoverLetter.objects.all(),
+                       widget=MultipleHiddenInput)
     class Meta:
         model = Event

More information about the Patchwork mailing list