We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
The same names with different capitalisation are seen as different
### Describe the bug
When claiming promo requests in the admin site, if the claimant name is entered twice, first without capital and then with one. It is counted as two different persons.

### Expected behaviour
The same name with different capitalisation should still count as the same name.


--- 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/promotion/admin.py`
Content:
```
1 """Registers admin interfaces for the models defined in this module."""
2 from django.contrib import admin
3 from django.contrib.admin import ModelAdmin
4 
5 from events.services import is_organiser
6 from promotion.forms import PromotionRequestForm
7 
8 from .models import PromotionChannel, PromotionRequest
9 
10 
11 @admin.register(PromotionRequest)
12 class PromotionRequestAdmin(admin.ModelAdmin):
13     """This manages the admin interface for the model items."""
14 
15     list_display = ("event", "publish_date", "channel", "assigned_to", "status")
16     list_filter = (
17         "publish_date",
18         "assigned_to",
19         "status",
20     )
21     date_hierarchy = "publish_date"
22     form = PromotionRequestForm
23     actions = ["mark_not_started", "mark_started", "mark_finished", "mark_published"]
24 
25     def has_change_permission(self, request, obj=None):
26         if obj is not None and obj.event and is_organiser(request.member, obj.event):
27             return True
28         return super().has_change_permission(request, obj)
29 
30     def mark_not_started(self, request, queryset):
31         """Change the status of the event to published."""
32         self._change_published(queryset, PromotionRequest.NOT_STARTED)
33 
34     mark_not_started.short_description = "Mark requests as not started"
35 
36     def mark_started(self, request, queryset):
37         """Change the status of the event to published."""
38         self._change_published(queryset, PromotionRequest.STARTED)
39 
40     mark_started.short_description = "Mark requests as started"
41 
42     def mark_finished(self, request, queryset):
43         """Change the status of the event to published."""
44         self._change_published(queryset, PromotionRequest.FINISHED)
45 
46     mark_finished.short_description = "Mark requests as finished"
47 
48     def mark_published(self, request, queryset):
49         """Change the status of the event to published."""
50         self._change_published(queryset, PromotionRequest.PUBLISHED)
51 
52     mark_published.short_description = "Mark requests as published"
53 
54     @staticmethod
55     def _change_published(queryset, status):
56         queryset.update(status=status)
57 
58 
59 @admin.register(PromotionChannel)
60 class PromotionChannelAdmin(ModelAdmin):
61     list_display = ("name", "publisher_reminder_email")
62
```
--- 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/promotion/admin.py b/website/promotion/admin.py
--- a/website/promotion/admin.py
+++ b/website/promotion/admin.py
@@ -1,6 +1,9 @@
 """Registers admin interfaces for the models defined in this module."""
+
 from django.contrib import admin
 from django.contrib.admin import ModelAdmin
+from django.db import models
+from django.db.models.functions import Lower
 
 from events.services import is_organiser
 from promotion.forms import PromotionRequestForm
@@ -8,6 +11,75 @@
 from .models import PromotionChannel, PromotionRequest
 
 
+class CaseInsensitiveFilter(admin.FieldListFilter):
+    def __init__(self, field, request, params, model, model_admin, field_path):
+        self.lookup_kwarg = f"{field_path}__iexact"
+        self.lookup_kwarg2 = f"{field_path}__isnull"
+        self.lookup_val = params.get(self.lookup_kwarg)
+        self.lookup_val2 = params.get(self.lookup_kwarg2)
+        super().__init__(field, request, params, model, model_admin, field_path)
+        self.empty_value_display = model_admin.get_empty_value_display()
+        queryset = model_admin.get_queryset(request)
+        lookup_choices = (
+            queryset.annotate(lowered=Lower(field.name))
+            .order_by(field.name)
+            .distinct()
+            .values_list(field.name, flat=True)
+        )
+        self.lookup_choices = set(
+            map(lambda x: x.lower() if x is not None else x, lookup_choices)
+        )
+
+    def get_facet_counts(self, pk_attname, filtered_qs):
+        return {
+            f"{i}__c": models.Count(
+                pk_attname,
+                filter=models.Q(
+                    (self.lookup_kwarg, value)
+                    if value is not None
+                    else (self.lookup_kwarg2, True)
+                ),
+            )
+            for i, value in enumerate(self.lookup_choices)
+        }
+
+    def choices(self, changelist):
+        add_facets = changelist.add_facets
+        facet_counts = self.get_facet_queryset(changelist)
+        yield {
+            "selected": self.lookup_val is None,
+            "query_string": changelist.get_query_string(
+                remove=[self.lookup_kwarg, self.lookup_kwarg2]
+            ),
+            "display": "All",
+        }
+        include_none = False
+        empty_title = self.empty_value_display
+        for key, val in enumerate(self.lookup_choices):
+            if add_facets:
+                count = facet_counts[f"{key}__c"]
+            if val is None:
+                include_none = True
+                empty_title = f"{empty_title} ({count})" if add_facets else empty_title
+                continue
+            yield {
+                "selected": self.lookup_val is not None and val in self.lookup_val,
+                "query_string": changelist.get_query_string({self.lookup_kwarg: val}),
+                "display": f"{val} ({count})" if add_facets else val,
+            }
+        if include_none:
+            yield {
+                "selected": self.lookup_val2 is True,
+                "query_string": changelist.get_query_string(
+                    {self.lookup_kwarg2: "True"}, remove=[self.lookup_kwarg]
+                ),
+                "display": empty_title,
+            }
+
+    def expected_parameters(self):
+        return [self.lookup_kwarg, self.lookup_kwarg2]
+
+
 @admin.register(PromotionRequest)
 class PromotionRequestAdmin(admin.ModelAdmin):
     """This manages the admin interface for the model items."""
@@ -15,7 +87,7 @@
     list_display = ("event", "publish_date", "channel", "assigned_to", "status")
     list_filter = (
         "publish_date",
-        "assigned_to",
+        ("assigned_to", CaseInsensitiveFilter),
         "status",
     )
     date_hierarchy = "publish_date"

{"golden_diff": "diff --git a/website/promotion/admin.py b/website/promotion/admin.py\n--- a/website/promotion/admin.py\n+++ b/website/promotion/admin.py\n@@ -1,6 +1,9 @@\n \"\"\"Registers admin interfaces for the models defined in this module.\"\"\"\n+\n from django.contrib import admin\n from django.contrib.admin import ModelAdmin\n+from django.db import models\n+from django.db.models.functions import Lower\n \n from events.services import is_organiser\n from promotion.forms import PromotionRequestForm\n@@ -8,6 +11,75 @@\n from .models import PromotionChannel, PromotionRequest\n \n \n+class CaseInsensitiveFilter(admin.FieldListFilter):\n+    def __init__(self, field, request, params, model, model_admin, field_path):\n+        self.lookup_kwarg = f\"{field_path}__iexact\"\n+        self.lookup_kwarg2 = f\"{field_path}__isnull\"\n+        self.lookup_val = params.get(self.lookup_kwarg)\n+        self.lookup_val2 = params.get(self.lookup_kwarg2)\n+        super().__init__(field, request, params, model, model_admin, field_path)\n+        self.empty_value_display = model_admin.get_empty_value_display()\n+        queryset = model_admin.get_queryset(request)\n+        lookup_choices = (\n+            queryset.annotate(lowered=Lower(field.name))\n+            .order_by(field.name)\n+            .distinct()\n+            .values_list(field.name, flat=True)\n+        )\n+        self.lookup_choices = set(\n+            map(lambda x: x.lower() if x is not None else x, lookup_choices)\n+        )\n+\n+    def get_facet_counts(self, pk_attname, filtered_qs):\n+        return {\n+            f\"{i}__c\": models.Count(\n+                pk_attname,\n+                filter=models.Q(\n+                    (self.lookup_kwarg, value)\n+                    if value is not None\n+                    else (self.lookup_kwarg2, True)\n+                ),\n+            )\n+            for i, value in enumerate(self.lookup_choices)\n+        }\n+\n+    def choices(self, changelist):\n+        add_facets = changelist.add_facets\n+        facet_counts = self.get_facet_queryset(changelist)\n+        yield {\n+            \"selected\": self.lookup_val is None,\n+            \"query_string\": changelist.get_query_string(\n+                remove=[self.lookup_kwarg, self.lookup_kwarg2]\n+            ),\n+            \"display\": \"All\",\n+        }\n+        include_none = False\n+        empty_title = self.empty_value_display\n+        for key, val in enumerate(self.lookup_choices):\n+            if add_facets:\n+                count = facet_counts[f\"{key}__c\"]\n+            if val is None:\n+                include_none = True\n+                empty_title = f\"{empty_title} ({count})\" if add_facets else empty_title\n+                continue\n+            yield {\n+                \"selected\": self.lookup_val is not None and val in self.lookup_val,\n+                \"query_string\": changelist.get_query_string({self.lookup_kwarg: val}),\n+                \"display\": f\"{val} ({count})\" if add_facets else val,\n+            }\n+        if include_none:\n+            yield {\n+                \"selected\": self.lookup_val2 is True,\n+                \"query_string\": changelist.get_query_string(\n+                    {self.lookup_kwarg2: \"True\"}, remove=[self.lookup_kwarg]\n+                ),\n+                \"display\": empty_title,\n+            }\n+\n+    def expected_parameters(self):\n+        return [self.lookup_kwarg, self.lookup_kwarg2]\n+\n+\n @admin.register(PromotionRequest)\n class PromotionRequestAdmin(admin.ModelAdmin):\n     \"\"\"This manages the admin interface for the model items.\"\"\"\n@@ -15,7 +87,7 @@\n     list_display = (\"event\", \"publish_date\", \"channel\", \"assigned_to\", \"status\")\n     list_filter = (\n         \"publish_date\",\n-        \"assigned_to\",\n+        (\"assigned_to\", CaseInsensitiveFilter),\n         \"status\",\n     )\n     date_hierarchy = \"publish_date\"\n", "issue": "The same names with different capitalisation are seen as different\n### Describe the bug\r\nWhen claiming promo requests in the admin site, if the claimant name is entered twice, first without capital and then with one. It is counted as two different persons.\r\n\r\n### Expected behaviour\r\nThe same name with different capitalisation should still count as the same name.\r\n\n", "before_files": [{"content": "\"\"\"Registers admin interfaces for the models defined in this module.\"\"\"\nfrom django.contrib import admin\nfrom django.contrib.admin import ModelAdmin\n\nfrom events.services import is_organiser\nfrom promotion.forms import PromotionRequestForm\n\nfrom .models import PromotionChannel, PromotionRequest\n\n\n@admin.register(PromotionRequest)\nclass PromotionRequestAdmin(admin.ModelAdmin):\n    \"\"\"This manages the admin interface for the model items.\"\"\"\n\n    list_display = (\"event\", \"publish_date\", \"channel\", \"assigned_to\", \"status\")\n    list_filter = (\n        \"publish_date\",\n        \"assigned_to\",\n        \"status\",\n    )\n    date_hierarchy = \"publish_date\"\n    form = PromotionRequestForm\n    actions = [\"mark_not_started\", \"mark_started\", \"mark_finished\", \"mark_published\"]\n\n    def has_change_permission(self, request, obj=None):\n        if obj is not None and obj.event and is_organiser(request.member, obj.event):\n            return True\n        return super().has_change_permission(request, obj)\n\n    def mark_not_started(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.NOT_STARTED)\n\n    mark_not_started.short_description = \"Mark requests as not started\"\n\n    def mark_started(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.STARTED)\n\n    mark_started.short_description = \"Mark requests as started\"\n\n    def mark_finished(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.FINISHED)\n\n    mark_finished.short_description = \"Mark requests as finished\"\n\n    def mark_published(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.PUBLISHED)\n\n    mark_published.short_description = \"Mark requests as published\"\n\n    @staticmethod\n    def _change_published(queryset, status):\n        queryset.update(status=status)\n\n\n@admin.register(PromotionChannel)\nclass PromotionChannelAdmin(ModelAdmin):\n    list_display = (\"name\", \"publisher_reminder_email\")\n", "path": "website/promotion/admin.py"}], "after_files": [{"content": "\"\"\"Registers admin interfaces for the models defined in this module.\"\"\"\n\nfrom django.contrib import admin\nfrom django.contrib.admin import ModelAdmin\nfrom django.db import models\nfrom django.db.models.functions import Lower\n\nfrom events.services import is_organiser\nfrom promotion.forms import PromotionRequestForm\n\nfrom .models import PromotionChannel, PromotionRequest\n\n\nclass CaseInsensitiveFilter(admin.FieldListFilter):\n    def __init__(self, field, request, params, model, model_admin, field_path):\n        self.lookup_kwarg = f\"{field_path}__iexact\"\n        self.lookup_kwarg2 = f\"{field_path}__isnull\"\n        self.lookup_val = params.get(self.lookup_kwarg)\n        self.lookup_val2 = params.get(self.lookup_kwarg2)\n        super().__init__(field, request, params, model, model_admin, field_path)\n        self.empty_value_display = model_admin.get_empty_value_display()\n        queryset = model_admin.get_queryset(request)\n        lookup_choices = (\n            queryset.annotate(lowered=Lower(field.name))\n            .order_by(field.name)\n            .distinct()\n            .values_list(field.name, flat=True)\n        )\n        self.lookup_choices = set(\n            map(lambda x: x.lower() if x is not None else x, lookup_choices)\n        )\n\n    def get_facet_counts(self, pk_attname, filtered_qs):\n        return {\n            f\"{i}__c\": models.Count(\n                pk_attname,\n                filter=models.Q(\n                    (self.lookup_kwarg, value)\n                    if value is not None\n                    else (self.lookup_kwarg2, True)\n                ),\n            )\n            for i, value in enumerate(self.lookup_choices)\n        }\n\n    def choices(self, changelist):\n        add_facets = changelist.add_facets\n        facet_counts = self.get_facet_queryset(changelist)\n        yield {\n            \"selected\": self.lookup_val is None,\n            \"query_string\": changelist.get_query_string(\n                remove=[self.lookup_kwarg, self.lookup_kwarg2]\n            ),\n            \"display\": \"All\",\n        }\n        include_none = False\n        empty_title = self.empty_value_display\n        for key, val in enumerate(self.lookup_choices):\n            if add_facets:\n                count = facet_counts[f\"{key}__c\"]\n            if val is None:\n                include_none = True\n                empty_title = f\"{empty_title} ({count})\" if add_facets else empty_title\n                continue\n            yield {\n                \"selected\": self.lookup_val is not None and val in self.lookup_val,\n                \"query_string\": changelist.get_query_string({self.lookup_kwarg: val}),\n                \"display\": f\"{val} ({count})\" if add_facets else val,\n            }\n        if include_none:\n            yield {\n                \"selected\": self.lookup_val2 is True,\n                \"query_string\": changelist.get_query_string(\n                    {self.lookup_kwarg2: \"True\"}, remove=[self.lookup_kwarg]\n                ),\n                \"display\": empty_title,\n            }\n\n    def expected_parameters(self):\n        return [self.lookup_kwarg, self.lookup_kwarg2]\n\n\n@admin.register(PromotionRequest)\nclass PromotionRequestAdmin(admin.ModelAdmin):\n    \"\"\"This manages the admin interface for the model items.\"\"\"\n\n    list_display = (\"event\", \"publish_date\", \"channel\", \"assigned_to\", \"status\")\n    list_filter = (\n        \"publish_date\",\n        (\"assigned_to\", CaseInsensitiveFilter),\n        \"status\",\n    )\n    date_hierarchy = \"publish_date\"\n    form = PromotionRequestForm\n    actions = [\"mark_not_started\", \"mark_started\", \"mark_finished\", \"mark_published\"]\n\n    def has_change_permission(self, request, obj=None):\n        if obj is not None and obj.event and is_organiser(request.member, obj.event):\n            return True\n        return super().has_change_permission(request, obj)\n\n    def mark_not_started(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.NOT_STARTED)\n\n    mark_not_started.short_description = \"Mark requests as not started\"\n\n    def mark_started(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.STARTED)\n\n    mark_started.short_description = \"Mark requests as started\"\n\n    def mark_finished(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.FINISHED)\n\n    mark_finished.short_description = \"Mark requests as finished\"\n\n    def mark_published(self, request, queryset):\n        \"\"\"Change the status of the event to published.\"\"\"\n        self._change_published(queryset, PromotionRequest.PUBLISHED)\n\n    mark_published.short_description = \"Mark requests as published\"\n\n    @staticmethod\n    def _change_published(queryset, status):\n        queryset.update(status=status)\n\n\n@admin.register(PromotionChannel)\nclass PromotionChannelAdmin(ModelAdmin):\n    list_display = (\"name\", \"publisher_reminder_email\")\n", "path": "website/promotion/admin.py"}]}