prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Subscription count does not correspond with displayed subscriptions
  **Problem**
  We do not show all subscriptions to a user - only those that we allow them to unsubscribe from. Subscriptions that are not shown to the user include permission request follows and upload-session follows, as well as "inactive" algorithm job follows (a necessary work around to allow unsubscribing from failed job notifications). The paginator on the listview, however, counts all subscriptions of the user, which leads to empty pages and a discrepancy in the shown vs. indicated number of subscriptions. 
  
  **Solution**
  We need to make sure that the paginator counts only the subscriptions that are actually shown to the user. 
  Simply showing all subscriptions sounds like a good alternative, but is not possible, because the inactive algorithm job follows should not be exposed to the user. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `app/grandchallenge/notifications/views.py`
  Content:
  ```
  1 from actstream.models import Follow
  2 from django.contrib import messages
  3 from django.contrib.messages.views import SuccessMessageMixin
  4 from django.views.generic import CreateView, DeleteView, ListView
  5 from guardian.mixins import (
  6     LoginRequiredMixin,
  7     PermissionListMixin,
  8     PermissionRequiredMixin as ObjectPermissionRequiredMixin,
  9 )
  10 from rest_framework import mixins, viewsets
  11 from rest_framework.permissions import DjangoObjectPermissions
  12 from rest_framework_guardian.filters import ObjectPermissionsFilter
  13 
  14 from grandchallenge.core.filters import FilterMixin
  15 from grandchallenge.notifications.filters import (
  16     FollowFilter,
  17     NotificationFilter,
  18 )
  19 from grandchallenge.notifications.forms import FollowForm
  20 from grandchallenge.notifications.models import Notification
  21 from grandchallenge.notifications.serializers import (
  22     FollowSerializer,
  23     NotificationSerializer,
  24 )
  25 from grandchallenge.notifications.utils import (
  26     prefetch_generic_foreign_key_objects,
  27 )
  28 from grandchallenge.subdomains.utils import reverse
  29 
  30 
  31 class NotificationViewSet(
  32     mixins.UpdateModelMixin,
  33     mixins.DestroyModelMixin,
  34     viewsets.ReadOnlyModelViewSet,
  35 ):
  36     queryset = Notification.objects.all()
  37     serializer_class = NotificationSerializer
  38     permission_classes = (DjangoObjectPermissions,)
  39     filter_backends = [ObjectPermissionsFilter]
  40 
  41     def destroy(self, request, *args, **kwargs):
  42         response = super().destroy(request, *args, **kwargs)
  43         messages.add_message(
  44             request, messages.SUCCESS, "Notifications successfully deleted.",
  45         )
  46         return response
  47 
  48     def update(self, request, *args, **kwargs):
  49         response = super().update(request, *args, **kwargs)
  50         messages.add_message(
  51             request, messages.SUCCESS, "Notifications successfully updated.",
  52         )
  53         return response
  54 
  55 
  56 class FollowViewSet(
  57     mixins.DestroyModelMixin,
  58     mixins.UpdateModelMixin,
  59     viewsets.ReadOnlyModelViewSet,
  60 ):
  61     queryset = Follow.objects.all()
  62     serializer_class = FollowSerializer
  63     permission_classes = (DjangoObjectPermissions,)
  64     filter_backends = [ObjectPermissionsFilter]
  65 
  66     def destroy(self, request, *args, **kwargs):
  67         response = super().destroy(request, *args, **kwargs)
  68         messages.add_message(
  69             request, messages.SUCCESS, "Subscription successfully deleted.",
  70         )
  71         return response
  72 
  73     def perform_update(self, serializer):
  74         messages.add_message(
  75             self.request,
  76             messages.SUCCESS,
  77             "Subscription successfully updated.",
  78         )
  79         return serializer.save()
  80 
  81 
  82 class NotificationList(
  83     LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView
  84 ):
  85     model = Notification
  86     permission_required = "view_notification"
  87     filter_class = NotificationFilter
  88     paginate_by = 50
  89 
  90     def get_queryset(self):
  91         return (
  92             super()
  93             .get_queryset()
  94             .select_related(
  95                 "actor_content_type",
  96                 "target_content_type",
  97                 "action_object_content_type",
  98                 "user__verification",
  99             )
  100             .order_by("-created")
  101         )
  102 
  103     def get_context_data(self, **kwargs):
  104         context = super().get_context_data(**kwargs)
  105 
  106         # Prefetch the object list here as at this point it has been paginated
  107         # which saves prefetching the related objects for all notifications
  108         context["object_list"] = prefetch_generic_foreign_key_objects(
  109             context["object_list"]
  110         )
  111 
  112         return context
  113 
  114 
  115 class FollowList(
  116     LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView
  117 ):
  118     model = Follow
  119     permission_required = "view_follow"
  120     filter_class = FollowFilter
  121     paginate_by = 50
  122 
  123     def get_queryset(self, *args, **kwargs):
  124         return (
  125             super()
  126             .get_queryset()
  127             .select_related("user", "content_type")
  128             .order_by("content_type")
  129         )
  130 
  131     def get_context_data(self, **kwargs):
  132         context = super().get_context_data(**kwargs)
  133 
  134         # Prefetch the object list here as at this point it has been paginated
  135         # which saves prefetching the related objects for all notifications
  136         context["object_list"] = prefetch_generic_foreign_key_objects(
  137             context["object_list"]
  138         )
  139         return context
  140 
  141 
  142 class FollowDelete(
  143     LoginRequiredMixin,
  144     ObjectPermissionRequiredMixin,
  145     SuccessMessageMixin,
  146     DeleteView,
  147 ):
  148     model = Follow
  149     success_message = "Subscription successfully deleted"
  150     permission_required = "delete_follow"
  151     raise_exception = True
  152 
  153     def get_permission_object(self):
  154         return self.get_object()
  155 
  156     def get_success_url(self):
  157         return reverse("notifications:follow-list")
  158 
  159 
  160 class FollowCreate(
  161     LoginRequiredMixin, SuccessMessageMixin, CreateView,
  162 ):
  163     model = Follow
  164     form_class = FollowForm
  165     success_message = "Subscription successfully added"
  166 
  167     def get_form_kwargs(self):
  168         kwargs = super().get_form_kwargs()
  169         kwargs.update({"user": self.request.user})
  170         return kwargs
  171 
  172     def get_success_url(self):
  173         return reverse("notifications:follow-list")
  174
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/app/grandchallenge/notifications/views.py b/app/grandchallenge/notifications/views.py
  --- a/app/grandchallenge/notifications/views.py
  +++ b/app/grandchallenge/notifications/views.py
  @@ -1,6 +1,7 @@
   from actstream.models import Follow
   from django.contrib import messages
   from django.contrib.messages.views import SuccessMessageMixin
  +from django.db.models import Q
   from django.views.generic import CreateView, DeleteView, ListView
   from guardian.mixins import (
       LoginRequiredMixin,
  @@ -119,14 +120,33 @@
       permission_required = "view_follow"
       filter_class = FollowFilter
       paginate_by = 50
  -
  -    def get_queryset(self, *args, **kwargs):
  -        return (
  -            super()
  -            .get_queryset()
  -            .select_related("user", "content_type")
  -            .order_by("content_type")
  +    queryset = (
  +        Follow.objects.exclude(
  +            Q(
  +                content_type__app_label="archives",
  +                content_type__model="archivepermissionrequest",
  +            )
  +            | Q(
  +                content_type__app_label="algorithms",
  +                content_type__model="algorithmpermissionrequest",
  +            )
  +            | Q(
  +                content_type__app_label="reader_studies",
  +                content_type__model="readerstudypermissionrequest",
  +            )
  +            | Q(
  +                content_type__app_label="participants",
  +                content_type__model="registrationrequest",
  +            )
  +            | Q(
  +                content_type__app_label="cases",
  +                content_type__model="rawimageuploadsessions",
  +            )
           )
  +        .exclude(flag="job-inactive")
  +        .select_related("user", "content_type")
  +        .order_by("content_type")
  +    )
   
       def get_context_data(self, **kwargs):
           context = super().get_context_data(**kwargs)
  @@ -136,6 +156,7 @@
           context["object_list"] = prefetch_generic_foreign_key_objects(
               context["object_list"]
           )
  +
           return context
  
verification_info: {"golden_diff": "diff --git a/app/grandchallenge/notifications/views.py b/app/grandchallenge/notifications/views.py\n--- a/app/grandchallenge/notifications/views.py\n+++ b/app/grandchallenge/notifications/views.py\n@@ -1,6 +1,7 @@\n from actstream.models import Follow\n from django.contrib import messages\n from django.contrib.messages.views import SuccessMessageMixin\n+from django.db.models import Q\n from django.views.generic import CreateView, DeleteView, ListView\n from guardian.mixins import (\n     LoginRequiredMixin,\n@@ -119,14 +120,33 @@\n     permission_required = \"view_follow\"\n     filter_class = FollowFilter\n     paginate_by = 50\n-\n-    def get_queryset(self, *args, **kwargs):\n-        return (\n-            super()\n-            .get_queryset()\n-            .select_related(\"user\", \"content_type\")\n-            .order_by(\"content_type\")\n+    queryset = (\n+        Follow.objects.exclude(\n+            Q(\n+                content_type__app_label=\"archives\",\n+                content_type__model=\"archivepermissionrequest\",\n+            )\n+            | Q(\n+                content_type__app_label=\"algorithms\",\n+                content_type__model=\"algorithmpermissionrequest\",\n+            )\n+            | Q(\n+                content_type__app_label=\"reader_studies\",\n+                content_type__model=\"readerstudypermissionrequest\",\n+            )\n+            | Q(\n+                content_type__app_label=\"participants\",\n+                content_type__model=\"registrationrequest\",\n+            )\n+            | Q(\n+                content_type__app_label=\"cases\",\n+                content_type__model=\"rawimageuploadsessions\",\n+            )\n         )\n+        .exclude(flag=\"job-inactive\")\n+        .select_related(\"user\", \"content_type\")\n+        .order_by(\"content_type\")\n+    )\n \n     def get_context_data(self, **kwargs):\n         context = super().get_context_data(**kwargs)\n@@ -136,6 +156,7 @@\n         context[\"object_list\"] = prefetch_generic_foreign_key_objects(\n             context[\"object_list\"]\n         )\n+\n         return context\n", "issue": "Subscription count does not correspond with displayed subscriptions\n**Problem**\r\nWe do not show all subscriptions to a user - only those that we allow them to unsubscribe from. Subscriptions that are not shown to the user include permission request follows and upload-session follows, as well as \"inactive\" algorithm job follows (a necessary work around to allow unsubscribing from failed job notifications). The paginator on the listview, however, counts all subscriptions of the user, which leads to empty pages and a discrepancy in the shown vs. indicated number of subscriptions. \r\n\r\n**Solution**\r\nWe need to make sure that the paginator counts only the subscriptions that are actually shown to the user. \r\nSimply showing all subscriptions sounds like a good alternative, but is not possible, because the inactive algorithm job follows should not be exposed to the user. \n", "before_files": [{"content": "from actstream.models import Follow\nfrom django.contrib import messages\nfrom django.contrib.messages.views import SuccessMessageMixin\nfrom django.views.generic import CreateView, DeleteView, ListView\nfrom guardian.mixins import (\n    LoginRequiredMixin,\n    PermissionListMixin,\n    PermissionRequiredMixin as ObjectPermissionRequiredMixin,\n)\nfrom rest_framework import mixins, viewsets\nfrom rest_framework.permissions import DjangoObjectPermissions\nfrom rest_framework_guardian.filters import ObjectPermissionsFilter\n\nfrom grandchallenge.core.filters import FilterMixin\nfrom grandchallenge.notifications.filters import (\n    FollowFilter,\n    NotificationFilter,\n)\nfrom grandchallenge.notifications.forms import FollowForm\nfrom grandchallenge.notifications.models import Notification\nfrom grandchallenge.notifications.serializers import (\n    FollowSerializer,\n    NotificationSerializer,\n)\nfrom grandchallenge.notifications.utils import (\n    prefetch_generic_foreign_key_objects,\n)\nfrom grandchallenge.subdomains.utils import reverse\n\n\nclass NotificationViewSet(\n    mixins.UpdateModelMixin,\n    mixins.DestroyModelMixin,\n    viewsets.ReadOnlyModelViewSet,\n):\n    queryset = Notification.objects.all()\n    serializer_class = NotificationSerializer\n    permission_classes = (DjangoObjectPermissions,)\n    filter_backends = [ObjectPermissionsFilter]\n\n    def destroy(self, request, *args, **kwargs):\n        response = super().destroy(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Notifications successfully deleted.\",\n        )\n        return response\n\n    def update(self, request, *args, **kwargs):\n        response = super().update(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Notifications successfully updated.\",\n        )\n        return response\n\n\nclass FollowViewSet(\n    mixins.DestroyModelMixin,\n    mixins.UpdateModelMixin,\n    viewsets.ReadOnlyModelViewSet,\n):\n    queryset = Follow.objects.all()\n    serializer_class = FollowSerializer\n    permission_classes = (DjangoObjectPermissions,)\n    filter_backends = [ObjectPermissionsFilter]\n\n    def destroy(self, request, *args, **kwargs):\n        response = super().destroy(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Subscription successfully deleted.\",\n        )\n        return response\n\n    def perform_update(self, serializer):\n        messages.add_message(\n            self.request,\n            messages.SUCCESS,\n            \"Subscription successfully updated.\",\n        )\n        return serializer.save()\n\n\nclass NotificationList(\n    LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView\n):\n    model = Notification\n    permission_required = \"view_notification\"\n    filter_class = NotificationFilter\n    paginate_by = 50\n\n    def get_queryset(self):\n        return (\n            super()\n            .get_queryset()\n            .select_related(\n                \"actor_content_type\",\n                \"target_content_type\",\n                \"action_object_content_type\",\n                \"user__verification\",\n            )\n            .order_by(\"-created\")\n        )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        # Prefetch the object list here as at this point it has been paginated\n        # which saves prefetching the related objects for all notifications\n        context[\"object_list\"] = prefetch_generic_foreign_key_objects(\n            context[\"object_list\"]\n        )\n\n        return context\n\n\nclass FollowList(\n    LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView\n):\n    model = Follow\n    permission_required = \"view_follow\"\n    filter_class = FollowFilter\n    paginate_by = 50\n\n    def get_queryset(self, *args, **kwargs):\n        return (\n            super()\n            .get_queryset()\n            .select_related(\"user\", \"content_type\")\n            .order_by(\"content_type\")\n        )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        # Prefetch the object list here as at this point it has been paginated\n        # which saves prefetching the related objects for all notifications\n        context[\"object_list\"] = prefetch_generic_foreign_key_objects(\n            context[\"object_list\"]\n        )\n        return context\n\n\nclass FollowDelete(\n    LoginRequiredMixin,\n    ObjectPermissionRequiredMixin,\n    SuccessMessageMixin,\n    DeleteView,\n):\n    model = Follow\n    success_message = \"Subscription successfully deleted\"\n    permission_required = \"delete_follow\"\n    raise_exception = True\n\n    def get_permission_object(self):\n        return self.get_object()\n\n    def get_success_url(self):\n        return reverse(\"notifications:follow-list\")\n\n\nclass FollowCreate(\n    LoginRequiredMixin, SuccessMessageMixin, CreateView,\n):\n    model = Follow\n    form_class = FollowForm\n    success_message = \"Subscription successfully added\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs.update({\"user\": self.request.user})\n        return kwargs\n\n    def get_success_url(self):\n        return reverse(\"notifications:follow-list\")\n", "path": "app/grandchallenge/notifications/views.py"}], "after_files": [{"content": "from actstream.models import Follow\nfrom django.contrib import messages\nfrom django.contrib.messages.views import SuccessMessageMixin\nfrom django.db.models import Q\nfrom django.views.generic import CreateView, DeleteView, ListView\nfrom guardian.mixins import (\n    LoginRequiredMixin,\n    PermissionListMixin,\n    PermissionRequiredMixin as ObjectPermissionRequiredMixin,\n)\nfrom rest_framework import mixins, viewsets\nfrom rest_framework.permissions import DjangoObjectPermissions\nfrom rest_framework_guardian.filters import ObjectPermissionsFilter\n\nfrom grandchallenge.core.filters import FilterMixin\nfrom grandchallenge.notifications.filters import (\n    FollowFilter,\n    NotificationFilter,\n)\nfrom grandchallenge.notifications.forms import FollowForm\nfrom grandchallenge.notifications.models import Notification\nfrom grandchallenge.notifications.serializers import (\n    FollowSerializer,\n    NotificationSerializer,\n)\nfrom grandchallenge.notifications.utils import (\n    prefetch_generic_foreign_key_objects,\n)\nfrom grandchallenge.subdomains.utils import reverse\n\n\nclass NotificationViewSet(\n    mixins.UpdateModelMixin,\n    mixins.DestroyModelMixin,\n    viewsets.ReadOnlyModelViewSet,\n):\n    queryset = Notification.objects.all()\n    serializer_class = NotificationSerializer\n    permission_classes = (DjangoObjectPermissions,)\n    filter_backends = [ObjectPermissionsFilter]\n\n    def destroy(self, request, *args, **kwargs):\n        response = super().destroy(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Notifications successfully deleted.\",\n        )\n        return response\n\n    def update(self, request, *args, **kwargs):\n        response = super().update(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Notifications successfully updated.\",\n        )\n        return response\n\n\nclass FollowViewSet(\n    mixins.DestroyModelMixin,\n    mixins.UpdateModelMixin,\n    viewsets.ReadOnlyModelViewSet,\n):\n    queryset = Follow.objects.all()\n    serializer_class = FollowSerializer\n    permission_classes = (DjangoObjectPermissions,)\n    filter_backends = [ObjectPermissionsFilter]\n\n    def destroy(self, request, *args, **kwargs):\n        response = super().destroy(request, *args, **kwargs)\n        messages.add_message(\n            request, messages.SUCCESS, \"Subscription successfully deleted.\",\n        )\n        return response\n\n    def perform_update(self, serializer):\n        messages.add_message(\n            self.request,\n            messages.SUCCESS,\n            \"Subscription successfully updated.\",\n        )\n        return serializer.save()\n\n\nclass NotificationList(\n    LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView\n):\n    model = Notification\n    permission_required = \"view_notification\"\n    filter_class = NotificationFilter\n    paginate_by = 50\n\n    def get_queryset(self):\n        return (\n            super()\n            .get_queryset()\n            .select_related(\n                \"actor_content_type\",\n                \"target_content_type\",\n                \"action_object_content_type\",\n                \"user__verification\",\n            )\n            .order_by(\"-created\")\n        )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        # Prefetch the object list here as at this point it has been paginated\n        # which saves prefetching the related objects for all notifications\n        context[\"object_list\"] = prefetch_generic_foreign_key_objects(\n            context[\"object_list\"]\n        )\n\n        return context\n\n\nclass FollowList(\n    LoginRequiredMixin, FilterMixin, PermissionListMixin, ListView\n):\n    model = Follow\n    permission_required = \"view_follow\"\n    filter_class = FollowFilter\n    paginate_by = 50\n    queryset = (\n        Follow.objects.exclude(\n            Q(\n                content_type__app_label=\"archives\",\n                content_type__model=\"archivepermissionrequest\",\n            )\n            | Q(\n                content_type__app_label=\"algorithms\",\n                content_type__model=\"algorithmpermissionrequest\",\n            )\n            | Q(\n                content_type__app_label=\"reader_studies\",\n                content_type__model=\"readerstudypermissionrequest\",\n            )\n            | Q(\n                content_type__app_label=\"participants\",\n                content_type__model=\"registrationrequest\",\n            )\n            | Q(\n                content_type__app_label=\"cases\",\n                content_type__model=\"rawimageuploadsessions\",\n            )\n        )\n        .exclude(flag=\"job-inactive\")\n        .select_related(\"user\", \"content_type\")\n        .order_by(\"content_type\")\n    )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        # Prefetch the object list here as at this point it has been paginated\n        # which saves prefetching the related objects for all notifications\n        context[\"object_list\"] = prefetch_generic_foreign_key_objects(\n            context[\"object_list\"]\n        )\n\n        return context\n\n\nclass FollowDelete(\n    LoginRequiredMixin,\n    ObjectPermissionRequiredMixin,\n    SuccessMessageMixin,\n    DeleteView,\n):\n    model = Follow\n    success_message = \"Subscription successfully deleted\"\n    permission_required = \"delete_follow\"\n    raise_exception = True\n\n    def get_permission_object(self):\n        return self.get_object()\n\n    def get_success_url(self):\n        return reverse(\"notifications:follow-list\")\n\n\nclass FollowCreate(\n    LoginRequiredMixin, SuccessMessageMixin, CreateView,\n):\n    model = Follow\n    form_class = FollowForm\n    success_message = \"Subscription successfully added\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs.update({\"user\": self.request.user})\n        return kwargs\n\n    def get_success_url(self):\n        return reverse(\"notifications:follow-list\")\n", "path": "app/grandchallenge/notifications/views.py"}]}