We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix "identical-code" issue in website/education/admin.py
Identical blocks of code found in 2 locations. Consider refactoring.

https://codeclimate.com/github/svthalia/concrexit/website/education/admin.py#issue_5ecfbb80e8d0fa00010003f6

--- 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/education/admin.py`
Content:
```
1 """
2 This module registers admin pages for the models
3 """
4 import csv
5 
6 from django.contrib import admin
7 from django.http import HttpResponse
8 from django.utils.translation import gettext_lazy as _
9 
10 from utils.translation import TranslatedModelAdmin
11 from . import models
12 from .forms import SummaryAdminForm
13 
14 admin.site.register(models.Category)
15 
16 
17 @admin.register(models.Course)
18 class CourseAdmin(TranslatedModelAdmin):
19     fields = (
20         "name",
21         "course_code",
22         "ec",
23         "since",
24         "until",
25         "categories",
26         "old_courses",
27     )
28     list_filter = ("categories", "ec")
29     search_fields = ("name", "course_code")
30 
31 
32 @admin.register(models.Exam)
33 class ExamAdmin(TranslatedModelAdmin):
34     list_display = (
35         "type",
36         "course",
37         "exam_date",
38         "uploader",
39         "accepted",
40         "language",
41         "download_count",
42     )
43     readonly_fields = ("download_count",)
44     list_filter = ("accepted", "exam_date", "type", "language")
45     search_fields = (
46         "name",
47         "uploader__first_name",
48         "uploader__last_name",
49         "course__name_nl",
50         "course__name_en",
51     )
52     actions = ["accept", "reject", "reset_download_count", "download_csv"]
53 
54     def accept(self, request, queryset):
55         queryset.update(accepted=True)
56 
57     accept.short_description = _("Mark exams as accepted")
58 
59     def reject(self, request, queryset):
60         queryset.update(accepted=False)
61 
62     reject.short_description = _("Mark exams as rejected")
63 
64     def reset_download_count(self, request, queryset):
65         queryset.update(download_count=0)
66 
67     reset_download_count.short_description = _("Reset the marked exams download count")
68 
69     def download_csv(self, request, queryset):
70         opts = queryset.model._meta
71         response = HttpResponse(content_type="text/csv")
72         # force download.
73         response["Content-Disposition"] = "attachment;filename=export.csv"
74         # the csv writer
75         writer = csv.writer(response)
76         field_names = [field.name for field in opts.fields]
77         # Write a first row with header information
78         writer.writerow(field_names)
79         # Write data rows
80         for obj in queryset:
81             writer.writerow([getattr(obj, field) for field in field_names])
82         return response
83 
84     download_csv.short_description = _("Download marked as csv")
85 
86 
87 @admin.register(models.Summary)
88 class SummaryAdmin(TranslatedModelAdmin):
89     list_display = (
90         "name",
91         "course",
92         "uploader",
93         "accepted",
94         "language",
95         "download_count",
96     )
97     readonly_fields = ("download_count",)
98     list_filter = ("accepted", "language")
99     search_fields = (
100         "name",
101         "uploader__first_name",
102         "uploader__last_name",
103         "course__name_nl",
104         "course__name_en",
105     )
106     actions = ["accept", "reject", "reset_download_count", "download_csv"]
107     form = SummaryAdminForm
108 
109     def accept(self, request, queryset):
110         queryset.update(accepted=True)
111 
112     accept.short_description = _("Mark summaries as accepted")
113 
114     def reject(self, request, queryset):
115         queryset.update(accepted=False)
116 
117     reject.short_description = _("Mark summaries as rejected")
118 
119     def reset_download_count(self, request, queryset):
120         queryset.update(download_count=0)
121 
122     reset_download_count.short_description = _(
123         "Reset the marked summaries download count"
124     )
125 
126     def download_csv(self, request, queryset):
127         opts = queryset.model._meta
128         response = HttpResponse(content_type="text/csv")
129         # force download.
130         response["Content-Disposition"] = "attachment;filename=export.csv"
131         # the csv writer
132         writer = csv.writer(response)
133         field_names = [field.name for field in opts.fields]
134         # Write a first row with header information
135         writer.writerow(field_names)
136         # Write data rows
137         for obj in queryset:
138             writer.writerow([getattr(obj, field) for field in field_names])
139         return response
140 
141     download_csv.short_description = _("Download marked as csv")
142
```
--- 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/education/admin.py b/website/education/admin.py
--- a/website/education/admin.py
+++ b/website/education/admin.py
@@ -29,8 +29,27 @@
     search_fields = ("name", "course_code")
 
 
+class WithDownloadCsv:
+    def download_csv(self, request, queryset):
+        opts = queryset.model._meta
+        response = HttpResponse(content_type="text/csv")
+        # force download.
+        response["Content-Disposition"] = "attachment;filename=export.csv"
+        # the csv writer
+        writer = csv.writer(response)
+        field_names = [field.name for field in opts.fields]
+        # Write a first row with header information
+        writer.writerow(field_names)
+        # Write data rows
+        for obj in queryset:
+            writer.writerow([getattr(obj, field) for field in field_names])
+        return response
+
+    download_csv.short_description = _("Download marked as csv")
+
+
 @admin.register(models.Exam)
-class ExamAdmin(TranslatedModelAdmin):
+class ExamAdmin(TranslatedModelAdmin, WithDownloadCsv):
     list_display = (
         "type",
         "course",
@@ -66,26 +85,9 @@
 
     reset_download_count.short_description = _("Reset the marked exams download count")
 
-    def download_csv(self, request, queryset):
-        opts = queryset.model._meta
-        response = HttpResponse(content_type="text/csv")
-        # force download.
-        response["Content-Disposition"] = "attachment;filename=export.csv"
-        # the csv writer
-        writer = csv.writer(response)
-        field_names = [field.name for field in opts.fields]
-        # Write a first row with header information
-        writer.writerow(field_names)
-        # Write data rows
-        for obj in queryset:
-            writer.writerow([getattr(obj, field) for field in field_names])
-        return response
-
-    download_csv.short_description = _("Download marked as csv")
-
 
 @admin.register(models.Summary)
-class SummaryAdmin(TranslatedModelAdmin):
+class SummaryAdmin(TranslatedModelAdmin, WithDownloadCsv):
     list_display = (
         "name",
         "course",
@@ -122,20 +124,3 @@
     reset_download_count.short_description = _(
         "Reset the marked summaries download count"
     )
-
-    def download_csv(self, request, queryset):
-        opts = queryset.model._meta
-        response = HttpResponse(content_type="text/csv")
-        # force download.
-        response["Content-Disposition"] = "attachment;filename=export.csv"
-        # the csv writer
-        writer = csv.writer(response)
-        field_names = [field.name for field in opts.fields]
-        # Write a first row with header information
-        writer.writerow(field_names)
-        # Write data rows
-        for obj in queryset:
-            writer.writerow([getattr(obj, field) for field in field_names])
-        return response
-
-    download_csv.short_description = _("Download marked as csv")

{"golden_diff": "diff --git a/website/education/admin.py b/website/education/admin.py\n--- a/website/education/admin.py\n+++ b/website/education/admin.py\n@@ -29,8 +29,27 @@\n     search_fields = (\"name\", \"course_code\")\n \n \n+class WithDownloadCsv:\n+    def download_csv(self, request, queryset):\n+        opts = queryset.model._meta\n+        response = HttpResponse(content_type=\"text/csv\")\n+        # force download.\n+        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n+        # the csv writer\n+        writer = csv.writer(response)\n+        field_names = [field.name for field in opts.fields]\n+        # Write a first row with header information\n+        writer.writerow(field_names)\n+        # Write data rows\n+        for obj in queryset:\n+            writer.writerow([getattr(obj, field) for field in field_names])\n+        return response\n+\n+    download_csv.short_description = _(\"Download marked as csv\")\n+\n+\n @admin.register(models.Exam)\n-class ExamAdmin(TranslatedModelAdmin):\n+class ExamAdmin(TranslatedModelAdmin, WithDownloadCsv):\n     list_display = (\n         \"type\",\n         \"course\",\n@@ -66,26 +85,9 @@\n \n     reset_download_count.short_description = _(\"Reset the marked exams download count\")\n \n-    def download_csv(self, request, queryset):\n-        opts = queryset.model._meta\n-        response = HttpResponse(content_type=\"text/csv\")\n-        # force download.\n-        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n-        # the csv writer\n-        writer = csv.writer(response)\n-        field_names = [field.name for field in opts.fields]\n-        # Write a first row with header information\n-        writer.writerow(field_names)\n-        # Write data rows\n-        for obj in queryset:\n-            writer.writerow([getattr(obj, field) for field in field_names])\n-        return response\n-\n-    download_csv.short_description = _(\"Download marked as csv\")\n-\n \n @admin.register(models.Summary)\n-class SummaryAdmin(TranslatedModelAdmin):\n+class SummaryAdmin(TranslatedModelAdmin, WithDownloadCsv):\n     list_display = (\n         \"name\",\n         \"course\",\n@@ -122,20 +124,3 @@\n     reset_download_count.short_description = _(\n         \"Reset the marked summaries download count\"\n     )\n-\n-    def download_csv(self, request, queryset):\n-        opts = queryset.model._meta\n-        response = HttpResponse(content_type=\"text/csv\")\n-        # force download.\n-        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n-        # the csv writer\n-        writer = csv.writer(response)\n-        field_names = [field.name for field in opts.fields]\n-        # Write a first row with header information\n-        writer.writerow(field_names)\n-        # Write data rows\n-        for obj in queryset:\n-            writer.writerow([getattr(obj, field) for field in field_names])\n-        return response\n-\n-    download_csv.short_description = _(\"Download marked as csv\")\n", "issue": "Fix \"identical-code\" issue in website/education/admin.py\nIdentical blocks of code found in 2 locations. Consider refactoring.\n\nhttps://codeclimate.com/github/svthalia/concrexit/website/education/admin.py#issue_5ecfbb80e8d0fa00010003f6\n", "before_files": [{"content": "\"\"\"\nThis module registers admin pages for the models\n\"\"\"\nimport csv\n\nfrom django.contrib import admin\nfrom django.http import HttpResponse\nfrom django.utils.translation import gettext_lazy as _\n\nfrom utils.translation import TranslatedModelAdmin\nfrom . import models\nfrom .forms import SummaryAdminForm\n\nadmin.site.register(models.Category)\n\n\n@admin.register(models.Course)\nclass CourseAdmin(TranslatedModelAdmin):\n    fields = (\n        \"name\",\n        \"course_code\",\n        \"ec\",\n        \"since\",\n        \"until\",\n        \"categories\",\n        \"old_courses\",\n    )\n    list_filter = (\"categories\", \"ec\")\n    search_fields = (\"name\", \"course_code\")\n\n\n@admin.register(models.Exam)\nclass ExamAdmin(TranslatedModelAdmin):\n    list_display = (\n        \"type\",\n        \"course\",\n        \"exam_date\",\n        \"uploader\",\n        \"accepted\",\n        \"language\",\n        \"download_count\",\n    )\n    readonly_fields = (\"download_count\",)\n    list_filter = (\"accepted\", \"exam_date\", \"type\", \"language\")\n    search_fields = (\n        \"name\",\n        \"uploader__first_name\",\n        \"uploader__last_name\",\n        \"course__name_nl\",\n        \"course__name_en\",\n    )\n    actions = [\"accept\", \"reject\", \"reset_download_count\", \"download_csv\"]\n\n    def accept(self, request, queryset):\n        queryset.update(accepted=True)\n\n    accept.short_description = _(\"Mark exams as accepted\")\n\n    def reject(self, request, queryset):\n        queryset.update(accepted=False)\n\n    reject.short_description = _(\"Mark exams as rejected\")\n\n    def reset_download_count(self, request, queryset):\n        queryset.update(download_count=0)\n\n    reset_download_count.short_description = _(\"Reset the marked exams download count\")\n\n    def download_csv(self, request, queryset):\n        opts = queryset.model._meta\n        response = HttpResponse(content_type=\"text/csv\")\n        # force download.\n        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n        # the csv writer\n        writer = csv.writer(response)\n        field_names = [field.name for field in opts.fields]\n        # Write a first row with header information\n        writer.writerow(field_names)\n        # Write data rows\n        for obj in queryset:\n            writer.writerow([getattr(obj, field) for field in field_names])\n        return response\n\n    download_csv.short_description = _(\"Download marked as csv\")\n\n\n@admin.register(models.Summary)\nclass SummaryAdmin(TranslatedModelAdmin):\n    list_display = (\n        \"name\",\n        \"course\",\n        \"uploader\",\n        \"accepted\",\n        \"language\",\n        \"download_count\",\n    )\n    readonly_fields = (\"download_count\",)\n    list_filter = (\"accepted\", \"language\")\n    search_fields = (\n        \"name\",\n        \"uploader__first_name\",\n        \"uploader__last_name\",\n        \"course__name_nl\",\n        \"course__name_en\",\n    )\n    actions = [\"accept\", \"reject\", \"reset_download_count\", \"download_csv\"]\n    form = SummaryAdminForm\n\n    def accept(self, request, queryset):\n        queryset.update(accepted=True)\n\n    accept.short_description = _(\"Mark summaries as accepted\")\n\n    def reject(self, request, queryset):\n        queryset.update(accepted=False)\n\n    reject.short_description = _(\"Mark summaries as rejected\")\n\n    def reset_download_count(self, request, queryset):\n        queryset.update(download_count=0)\n\n    reset_download_count.short_description = _(\n        \"Reset the marked summaries download count\"\n    )\n\n    def download_csv(self, request, queryset):\n        opts = queryset.model._meta\n        response = HttpResponse(content_type=\"text/csv\")\n        # force download.\n        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n        # the csv writer\n        writer = csv.writer(response)\n        field_names = [field.name for field in opts.fields]\n        # Write a first row with header information\n        writer.writerow(field_names)\n        # Write data rows\n        for obj in queryset:\n            writer.writerow([getattr(obj, field) for field in field_names])\n        return response\n\n    download_csv.short_description = _(\"Download marked as csv\")\n", "path": "website/education/admin.py"}], "after_files": [{"content": "\"\"\"\nThis module registers admin pages for the models\n\"\"\"\nimport csv\n\nfrom django.contrib import admin\nfrom django.http import HttpResponse\nfrom django.utils.translation import gettext_lazy as _\n\nfrom utils.translation import TranslatedModelAdmin\nfrom . import models\nfrom .forms import SummaryAdminForm\n\nadmin.site.register(models.Category)\n\n\n@admin.register(models.Course)\nclass CourseAdmin(TranslatedModelAdmin):\n    fields = (\n        \"name\",\n        \"course_code\",\n        \"ec\",\n        \"since\",\n        \"until\",\n        \"categories\",\n        \"old_courses\",\n    )\n    list_filter = (\"categories\", \"ec\")\n    search_fields = (\"name\", \"course_code\")\n\n\nclass WithDownloadCsv:\n    def download_csv(self, request, queryset):\n        opts = queryset.model._meta\n        response = HttpResponse(content_type=\"text/csv\")\n        # force download.\n        response[\"Content-Disposition\"] = \"attachment;filename=export.csv\"\n        # the csv writer\n        writer = csv.writer(response)\n        field_names = [field.name for field in opts.fields]\n        # Write a first row with header information\n        writer.writerow(field_names)\n        # Write data rows\n        for obj in queryset:\n            writer.writerow([getattr(obj, field) for field in field_names])\n        return response\n\n    download_csv.short_description = _(\"Download marked as csv\")\n\n\n@admin.register(models.Exam)\nclass ExamAdmin(TranslatedModelAdmin, WithDownloadCsv):\n    list_display = (\n        \"type\",\n        \"course\",\n        \"exam_date\",\n        \"uploader\",\n        \"accepted\",\n        \"language\",\n        \"download_count\",\n    )\n    readonly_fields = (\"download_count\",)\n    list_filter = (\"accepted\", \"exam_date\", \"type\", \"language\")\n    search_fields = (\n        \"name\",\n        \"uploader__first_name\",\n        \"uploader__last_name\",\n        \"course__name_nl\",\n        \"course__name_en\",\n    )\n    actions = [\"accept\", \"reject\", \"reset_download_count\", \"download_csv\"]\n\n    def accept(self, request, queryset):\n        queryset.update(accepted=True)\n\n    accept.short_description = _(\"Mark exams as accepted\")\n\n    def reject(self, request, queryset):\n        queryset.update(accepted=False)\n\n    reject.short_description = _(\"Mark exams as rejected\")\n\n    def reset_download_count(self, request, queryset):\n        queryset.update(download_count=0)\n\n    reset_download_count.short_description = _(\"Reset the marked exams download count\")\n\n\n@admin.register(models.Summary)\nclass SummaryAdmin(TranslatedModelAdmin, WithDownloadCsv):\n    list_display = (\n        \"name\",\n        \"course\",\n        \"uploader\",\n        \"accepted\",\n        \"language\",\n        \"download_count\",\n    )\n    readonly_fields = (\"download_count\",)\n    list_filter = (\"accepted\", \"language\")\n    search_fields = (\n        \"name\",\n        \"uploader__first_name\",\n        \"uploader__last_name\",\n        \"course__name_nl\",\n        \"course__name_en\",\n    )\n    actions = [\"accept\", \"reject\", \"reset_download_count\", \"download_csv\"]\n    form = SummaryAdminForm\n\n    def accept(self, request, queryset):\n        queryset.update(accepted=True)\n\n    accept.short_description = _(\"Mark summaries as accepted\")\n\n    def reject(self, request, queryset):\n        queryset.update(accepted=False)\n\n    reject.short_description = _(\"Mark summaries as rejected\")\n\n    def reset_download_count(self, request, queryset):\n        queryset.update(download_count=0)\n\n    reset_download_count.short_description = _(\n        \"Reset the marked summaries download count\"\n    )\n", "path": "website/education/admin.py"}]}