We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Albums pagination doesn't maintain search terms
### Describe the bug
If you open https://thalia.nu/members/photos/?keywords=borrel#photos-albums, then go to the second page using the pagination buttons, the search term is dropped.

### Expected behaviour
<!-- A clear and concise description of what you expected to happen. -->
The search term remains

### Additional context
<!-- Add any other context about the problem here. -->
Could be since we introduced the shared paginated view template? So it's quite likely this occurs for other paginated filterable/searchable views as well.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `website/thaliawebsite/views.py`
Content:
```
1 """General views for the website."""
2 
3 from django.contrib.admin.views.decorators import staff_member_required
4 from django.contrib.auth.views import LoginView, PasswordResetView
5 from django.core.exceptions import PermissionDenied
6 from django.http import HttpResponse, HttpResponseForbidden
7 from django.shortcuts import redirect
8 from django.utils.decorators import method_decorator
9 from django.views.generic import ListView, TemplateView
10 from django.views.generic.base import View
11 
12 from django_ratelimit.decorators import ratelimit
13 
14 
15 class IndexView(TemplateView):
16     template_name = "index.html"
17 
18 
19 @method_decorator(staff_member_required, "dispatch")
20 class TestCrashView(View):
21     """Test view to intentionally crash to test the error handling."""
22 
23     def dispatch(self, request, *args, **kwargs) -> HttpResponse:
24         if not request.user.is_superuser:
25             return HttpResponseForbidden("This is not for you")
26         raise Exception("Test exception")
27 
28 
29 class PagedView(ListView):
30     """A ListView with automatic pagination."""
31 
32     def get_context_data(self, **kwargs) -> dict:
33         context = super().get_context_data(**kwargs)
34         page = context["page_obj"].number
35         paginator = context["paginator"]
36 
37         # Show the two pages before and after the current page
38         page_range_start = max(1, page - 2)
39         page_range_stop = min(page + 3, paginator.num_pages + 1)
40 
41         # Add extra pages if we show less than 5 pages
42         page_range_start = min(page_range_start, page_range_stop - 5)
43         page_range_start = max(1, page_range_start)
44 
45         # Add extra pages if we still show less than 5 pages
46         page_range_stop = max(page_range_stop, page_range_start + 5)
47         page_range_stop = min(page_range_stop, paginator.num_pages + 1)
48 
49         page_range = range(page_range_start, page_range_stop)
50 
51         context.update(
52             {
53                 "page_range": page_range,
54             }
55         )
56 
57         return context
58 
59 
60 class RateLimitedPasswordResetView(PasswordResetView):
61     @method_decorator(ratelimit(key="ip", rate="5/h"))
62     def post(self, request, *args, **kwargs):
63         return super().post(request, *args, **kwargs)
64 
65 
66 class RateLimitedLoginView(LoginView):
67     @method_decorator(ratelimit(key="ip", rate="30/h"))
68     @method_decorator(ratelimit(key="post:username", rate="30/h"))
69     def post(self, request, *args, **kwargs):
70         return super().post(request, *args, **kwargs)
71 
72 
73 def rate_limited_view(request, *args, **kwargs):
74     return HttpResponse("You are rate limited", status=429)
75 
76 
77 def admin_unauthorized_view(request):
78     if not request.member:
79         url = "/user/login"
80         args = request.META.get("QUERY_STRING", "")
81         if args:
82             url = f"{url}?{args}"
83         return redirect(url)
84     elif not request.member.is_staff and not request.member.is_superuser:
85         raise PermissionDenied("You are not allowed to access the administration page.")
86     else:
87         return redirect(request.GET.get("next", "/"))
88
```
--- 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()

```

diff --git a/website/thaliawebsite/views.py b/website/thaliawebsite/views.py
--- a/website/thaliawebsite/views.py
+++ b/website/thaliawebsite/views.py
@@ -31,6 +31,7 @@
 
     def get_context_data(self, **kwargs) -> dict:
         context = super().get_context_data(**kwargs)
+        print(kwargs)
         page = context["page_obj"].number
         paginator = context["paginator"]
 
@@ -48,9 +49,17 @@
 
         page_range = range(page_range_start, page_range_stop)
 
+        querydict = self.request.GET.copy()
+
+        if "page" in querydict:
+            del querydict["page"]
+
         context.update(
             {
                 "page_range": page_range,
+                "base_url": f"{self.request.path}?{querydict.urlencode()}&"
+                if querydict
+                else f"{self.request.path}?",
             }
         )

{"golden_diff": "diff --git a/website/thaliawebsite/views.py b/website/thaliawebsite/views.py\n--- a/website/thaliawebsite/views.py\n+++ b/website/thaliawebsite/views.py\n@@ -31,6 +31,7 @@\n \n     def get_context_data(self, **kwargs) -> dict:\n         context = super().get_context_data(**kwargs)\n+        print(kwargs)\n         page = context[\"page_obj\"].number\n         paginator = context[\"paginator\"]\n \n@@ -48,9 +49,17 @@\n \n         page_range = range(page_range_start, page_range_stop)\n \n+        querydict = self.request.GET.copy()\n+\n+        if \"page\" in querydict:\n+            del querydict[\"page\"]\n+\n         context.update(\n             {\n                 \"page_range\": page_range,\n+                \"base_url\": f\"{self.request.path}?{querydict.urlencode()}&\"\n+                if querydict\n+                else f\"{self.request.path}?\",\n             }\n         )\n", "issue": "Albums pagination doesn't maintain search terms\n### Describe the bug\r\nIf you open https://thalia.nu/members/photos/?keywords=borrel#photos-albums, then go to the second page using the pagination buttons, the search term is dropped.\r\n\r\n### Expected behaviour\r\n<!-- A clear and concise description of what you expected to happen. -->\r\nThe search term remains\r\n\r\n### Additional context\r\n<!-- Add any other context about the problem here. -->\r\nCould be since we introduced the shared paginated view template? So it's quite likely this occurs for other paginated filterable/searchable views as well.\n", "before_files": [{"content": "\"\"\"General views for the website.\"\"\"\n\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.views import LoginView, PasswordResetView\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import HttpResponse, HttpResponseForbidden\nfrom django.shortcuts import redirect\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import ListView, TemplateView\nfrom django.views.generic.base import View\n\nfrom django_ratelimit.decorators import ratelimit\n\n\nclass IndexView(TemplateView):\n    template_name = \"index.html\"\n\n\n@method_decorator(staff_member_required, \"dispatch\")\nclass TestCrashView(View):\n    \"\"\"Test view to intentionally crash to test the error handling.\"\"\"\n\n    def dispatch(self, request, *args, **kwargs) -> HttpResponse:\n        if not request.user.is_superuser:\n            return HttpResponseForbidden(\"This is not for you\")\n        raise Exception(\"Test exception\")\n\n\nclass PagedView(ListView):\n    \"\"\"A ListView with automatic pagination.\"\"\"\n\n    def get_context_data(self, **kwargs) -> dict:\n        context = super().get_context_data(**kwargs)\n        page = context[\"page_obj\"].number\n        paginator = context[\"paginator\"]\n\n        # Show the two pages before and after the current page\n        page_range_start = max(1, page - 2)\n        page_range_stop = min(page + 3, paginator.num_pages + 1)\n\n        # Add extra pages if we show less than 5 pages\n        page_range_start = min(page_range_start, page_range_stop - 5)\n        page_range_start = max(1, page_range_start)\n\n        # Add extra pages if we still show less than 5 pages\n        page_range_stop = max(page_range_stop, page_range_start + 5)\n        page_range_stop = min(page_range_stop, paginator.num_pages + 1)\n\n        page_range = range(page_range_start, page_range_stop)\n\n        context.update(\n            {\n                \"page_range\": page_range,\n            }\n        )\n\n        return context\n\n\nclass RateLimitedPasswordResetView(PasswordResetView):\n    @method_decorator(ratelimit(key=\"ip\", rate=\"5/h\"))\n    def post(self, request, *args, **kwargs):\n        return super().post(request, *args, **kwargs)\n\n\nclass RateLimitedLoginView(LoginView):\n    @method_decorator(ratelimit(key=\"ip\", rate=\"30/h\"))\n    @method_decorator(ratelimit(key=\"post:username\", rate=\"30/h\"))\n    def post(self, request, *args, **kwargs):\n        return super().post(request, *args, **kwargs)\n\n\ndef rate_limited_view(request, *args, **kwargs):\n    return HttpResponse(\"You are rate limited\", status=429)\n\n\ndef admin_unauthorized_view(request):\n    if not request.member:\n        url = \"/user/login\"\n        args = request.META.get(\"QUERY_STRING\", \"\")\n        if args:\n            url = f\"{url}?{args}\"\n        return redirect(url)\n    elif not request.member.is_staff and not request.member.is_superuser:\n        raise PermissionDenied(\"You are not allowed to access the administration page.\")\n    else:\n        return redirect(request.GET.get(\"next\", \"/\"))\n", "path": "website/thaliawebsite/views.py"}], "after_files": [{"content": "\"\"\"General views for the website.\"\"\"\n\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.views import LoginView, PasswordResetView\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import HttpResponse, HttpResponseForbidden\nfrom django.shortcuts import redirect\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import ListView, TemplateView\nfrom django.views.generic.base import View\n\nfrom django_ratelimit.decorators import ratelimit\n\n\nclass IndexView(TemplateView):\n    template_name = \"index.html\"\n\n\n@method_decorator(staff_member_required, \"dispatch\")\nclass TestCrashView(View):\n    \"\"\"Test view to intentionally crash to test the error handling.\"\"\"\n\n    def dispatch(self, request, *args, **kwargs) -> HttpResponse:\n        if not request.user.is_superuser:\n            return HttpResponseForbidden(\"This is not for you\")\n        raise Exception(\"Test exception\")\n\n\nclass PagedView(ListView):\n    \"\"\"A ListView with automatic pagination.\"\"\"\n\n    def get_context_data(self, **kwargs) -> dict:\n        context = super().get_context_data(**kwargs)\n        print(kwargs)\n        page = context[\"page_obj\"].number\n        paginator = context[\"paginator\"]\n\n        # Show the two pages before and after the current page\n        page_range_start = max(1, page - 2)\n        page_range_stop = min(page + 3, paginator.num_pages + 1)\n\n        # Add extra pages if we show less than 5 pages\n        page_range_start = min(page_range_start, page_range_stop - 5)\n        page_range_start = max(1, page_range_start)\n\n        # Add extra pages if we still show less than 5 pages\n        page_range_stop = max(page_range_stop, page_range_start + 5)\n        page_range_stop = min(page_range_stop, paginator.num_pages + 1)\n\n        page_range = range(page_range_start, page_range_stop)\n\n        querydict = self.request.GET.copy()\n\n        if \"page\" in querydict:\n            del querydict[\"page\"]\n\n        context.update(\n            {\n                \"page_range\": page_range,\n                \"base_url\": f\"{self.request.path}?{querydict.urlencode()}&\"\n                if querydict\n                else f\"{self.request.path}?\",\n            }\n        )\n\n        return context\n\n\nclass RateLimitedPasswordResetView(PasswordResetView):\n    @method_decorator(ratelimit(key=\"ip\", rate=\"5/h\"))\n    def post(self, request, *args, **kwargs):\n        return super().post(request, *args, **kwargs)\n\n\nclass RateLimitedLoginView(LoginView):\n    @method_decorator(ratelimit(key=\"ip\", rate=\"30/h\"))\n    @method_decorator(ratelimit(key=\"post:username\", rate=\"30/h\"))\n    def post(self, request, *args, **kwargs):\n        return super().post(request, *args, **kwargs)\n\n\ndef rate_limited_view(request, *args, **kwargs):\n    return HttpResponse(\"You are rate limited\", status=429)\n\n\ndef admin_unauthorized_view(request):\n    if not request.member:\n        url = \"/user/login\"\n        args = request.META.get(\"QUERY_STRING\", \"\")\n        if args:\n            url = f\"{url}?{args}\"\n        return redirect(url)\n    elif not request.member.is_staff and not request.member.is_superuser:\n        raise PermissionDenied(\"You are not allowed to access the administration page.\")\n    else:\n        return redirect(request.GET.get(\"next\", \"/\"))\n", "path": "website/thaliawebsite/views.py"}]}