We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Allow to exclude courses from grader view
It should be possible to exclude courses from the semester overview on the grading page.
Single results should never be listed on the page and there should be a new attribute for each course defining whether the course is shown for graders or not.
This must also include a symbol for staff users, showing them that this course can't get grade documents.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `evap/grades/views.py`
Content:
```
1 from django.shortcuts import get_object_or_404, render, redirect
2 from django.db.models import Prefetch
3 from django.contrib import messages
4 from django.utils.translation import ugettext as _
5 from django.http import HttpResponseBadRequest, HttpResponseForbidden
6 
7 from sendfile import sendfile
8 
9 from evap.evaluation.auth import grade_publisher_required, grade_downloader_required, grade_publisher_or_staff_required
10 from evap.evaluation.models import Semester, Contribution, Course
11 from evap.grades.models import GradeDocument
12 from evap.grades.forms import GradeDocumentForm
13 from evap.evaluation.tools import send_publish_notifications
14 
15 
16 @grade_publisher_required
17 def index(request):
18     template_data = dict(
19         semesters=Semester.objects.all()
20     )
21     return render(request, "grades_index.html", template_data)
22 
23 
24 def prefetch_data(courses):
25     courses = courses.prefetch_related(
26         Prefetch("contributions", queryset=Contribution.objects.filter(responsible=True).select_related("contributor"), to_attr="responsible_contribution"),
27         "degrees")
28 
29     course_data = []
30     for course in courses:
31         course.responsible_contributor = course.responsible_contribution[0].contributor
32         course_data.append((
33             course,
34             GradeDocument.objects.filter(course=course, type=GradeDocument.MIDTERM_GRADES).count(),
35             GradeDocument.objects.filter(course=course, type=GradeDocument.FINAL_GRADES).count()
36         ))
37 
38     return course_data
39 
40 
41 @grade_publisher_required
42 def semester_view(request, semester_id):
43     semester = get_object_or_404(Semester, id=semester_id)
44 
45     courses = semester.course_set.exclude(state='new')
46     courses = prefetch_data(courses)
47 
48     template_data = dict(
49         semester=semester,
50         courses=courses,
51         disable_if_archived="disabled=disabled" if semester.is_archived else "",
52         disable_breadcrumb_semester=True,
53     )
54     return render(request, "grades_semester_view.html", template_data)
55 
56 
57 @grade_publisher_or_staff_required
58 def course_view(request, semester_id, course_id):
59     semester = get_object_or_404(Semester, id=semester_id)
60     course = get_object_or_404(Course, id=course_id)
61     is_grade_publisher = request.user.is_grade_publisher
62 
63     template_data = dict(
64         semester=semester,
65         course=course,
66         grade_documents=course.grade_documents.all(),
67         disable_if_archived="disabled=disabled" if semester.is_archived else "",
68         disable_breadcrumb_course=True,
69         is_grade_publisher=is_grade_publisher,
70     )
71     return render(request, "grades_course_view.html", template_data)
72 
73 
74 @grade_publisher_required
75 def upload_grades(request, semester_id, course_id):
76     semester = get_object_or_404(Semester, id=semester_id)
77     course = get_object_or_404(Course, id=course_id)
78 
79     final_grades = request.GET.get('final', 'false') # default: midterm grades
80     final_grades = {'true': True, 'false': False}.get(final_grades.lower()) # convert parameter to boolean
81 
82     form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, user=request.user)
83 
84     if form.is_valid():
85         form.save()
86         if final_grades and course.state == 'reviewed':
87             course.publish()
88             course.save()
89             send_publish_notifications(grade_document_courses=[course], evaluation_results_courses=[course])
90         else:
91             send_publish_notifications(grade_document_courses=[course])            
92 
93         messages.success(request, _("Successfully uploaded grades."))
94         return redirect('grades:course_view', semester.id, course.id)
95     else:
96         template_data = dict(
97             semester=semester,
98             course=course,
99             form=form,
100             final_grades=final_grades,
101             show_automated_publishing_info=final_grades,
102         )
103         return render(request, "grades_upload_form.html", template_data)
104 
105 
106 @grade_publisher_required
107 def toggle_no_grades(request, semester_id, course_id):
108     semester = get_object_or_404(Semester, id=semester_id)
109     course = get_object_or_404(Course, id=course_id)
110 
111     if request.method == 'POST':
112         course.gets_no_grade_documents = not course.gets_no_grade_documents
113         course.save()
114         
115         if course.gets_no_grade_documents:
116             if course.state == 'reviewed':
117                 course.publish()
118                 course.save()
119                 send_publish_notifications(evaluation_results_courses=[course])
120             messages.success(request, _("Successfully confirmed that no grade documents will be provided."))
121         else:
122             messages.success(request, _("Successfully confirmed that grade documents will be provided later on."))
123         return redirect('grades:semester_view', semester_id)
124     else:
125         template_data = dict(
126             semester=semester,
127             course=course,
128         )
129         return render(request, "toggle_no_grades.html", template_data)
130 
131 
132 @grade_downloader_required
133 def download_grades(request, grade_document_id):
134     if not request.method == "GET":
135         return HttpResponseBadRequest()
136 
137     grade_document = get_object_or_404(GradeDocument, id=grade_document_id)
138     return sendfile(request, grade_document.file.path, attachment=True, attachment_filename=grade_document.filename())
139 
140 
141 @grade_publisher_required
142 def edit_grades(request, semester_id, course_id, grade_document_id):
143     semester = get_object_or_404(Semester, id=semester_id)
144     course = get_object_or_404(Course, id=course_id)
145     grade_document = get_object_or_404(GradeDocument, id=grade_document_id)
146     final_grades = grade_document.type == GradeDocument.FINAL_GRADES
147 
148     form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, instance=grade_document, user=request.user)
149 
150     if form.is_valid():
151         form.save()
152         messages.success(request, _("Successfully updated grades."))
153         return redirect('grades:course_view', semester.id, course.id)
154     else:
155         template_data = dict(
156             semester=semester,
157             course=course,
158             form=form,
159             show_automated_publishing_info=False,
160         )
161         return render(request, "grades_upload_form.html", template_data)
162 
163 
164 @grade_publisher_required
165 def delete_grades(request, semester_id, course_id, grade_document_id):
166     semester = get_object_or_404(Semester, id=semester_id)
167     course = get_object_or_404(Course, id=course_id)
168     grade_document = get_object_or_404(GradeDocument, id=grade_document_id)
169 
170     if request.method == 'POST':
171         grade_document.delete()
172         messages.success(request, _("Successfully deleted grade document."))
173         return redirect('grades:course_view', semester_id, course_id)
174     else:
175         template_data = dict(
176             semester=semester,
177             course=course,
178             grade_document=grade_document,
179         )
180         return render(request, "grades_delete.html", template_data)
181
```
--- 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/evap/grades/views.py b/evap/grades/views.py
--- a/evap/grades/views.py
+++ b/evap/grades/views.py
@@ -42,7 +42,7 @@
 def semester_view(request, semester_id):
     semester = get_object_or_404(Semester, id=semester_id)
 
-    courses = semester.course_set.exclude(state='new')
+    courses = semester.course_set.filter(is_graded=True).exclude(state='new')
     courses = prefetch_data(courses)
 
     template_data = dict(

{"golden_diff": "diff --git a/evap/grades/views.py b/evap/grades/views.py\n--- a/evap/grades/views.py\n+++ b/evap/grades/views.py\n@@ -42,7 +42,7 @@\n def semester_view(request, semester_id):\n     semester = get_object_or_404(Semester, id=semester_id)\n \n-    courses = semester.course_set.exclude(state='new')\n+    courses = semester.course_set.filter(is_graded=True).exclude(state='new')\n     courses = prefetch_data(courses)\n \n     template_data = dict(\n", "issue": "Allow to exclude courses from grader view\nIt should be possible to exclude courses from the semester overview on the grading page.\nSingle results should never be listed on the page and there should be a new attribute for each course defining whether the course is shown for graders or not.\nThis must also include a symbol for staff users, showing them that this course can't get grade documents.\n\n", "before_files": [{"content": "from django.shortcuts import get_object_or_404, render, redirect\nfrom django.db.models import Prefetch\nfrom django.contrib import messages\nfrom django.utils.translation import ugettext as _\nfrom django.http import HttpResponseBadRequest, HttpResponseForbidden\n\nfrom sendfile import sendfile\n\nfrom evap.evaluation.auth import grade_publisher_required, grade_downloader_required, grade_publisher_or_staff_required\nfrom evap.evaluation.models import Semester, Contribution, Course\nfrom evap.grades.models import GradeDocument\nfrom evap.grades.forms import GradeDocumentForm\nfrom evap.evaluation.tools import send_publish_notifications\n\n\n@grade_publisher_required\ndef index(request):\n    template_data = dict(\n        semesters=Semester.objects.all()\n    )\n    return render(request, \"grades_index.html\", template_data)\n\n\ndef prefetch_data(courses):\n    courses = courses.prefetch_related(\n        Prefetch(\"contributions\", queryset=Contribution.objects.filter(responsible=True).select_related(\"contributor\"), to_attr=\"responsible_contribution\"),\n        \"degrees\")\n\n    course_data = []\n    for course in courses:\n        course.responsible_contributor = course.responsible_contribution[0].contributor\n        course_data.append((\n            course,\n            GradeDocument.objects.filter(course=course, type=GradeDocument.MIDTERM_GRADES).count(),\n            GradeDocument.objects.filter(course=course, type=GradeDocument.FINAL_GRADES).count()\n        ))\n\n    return course_data\n\n\n@grade_publisher_required\ndef semester_view(request, semester_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n\n    courses = semester.course_set.exclude(state='new')\n    courses = prefetch_data(courses)\n\n    template_data = dict(\n        semester=semester,\n        courses=courses,\n        disable_if_archived=\"disabled=disabled\" if semester.is_archived else \"\",\n        disable_breadcrumb_semester=True,\n    )\n    return render(request, \"grades_semester_view.html\", template_data)\n\n\n@grade_publisher_or_staff_required\ndef course_view(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    is_grade_publisher = request.user.is_grade_publisher\n\n    template_data = dict(\n        semester=semester,\n        course=course,\n        grade_documents=course.grade_documents.all(),\n        disable_if_archived=\"disabled=disabled\" if semester.is_archived else \"\",\n        disable_breadcrumb_course=True,\n        is_grade_publisher=is_grade_publisher,\n    )\n    return render(request, \"grades_course_view.html\", template_data)\n\n\n@grade_publisher_required\ndef upload_grades(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n\n    final_grades = request.GET.get('final', 'false') # default: midterm grades\n    final_grades = {'true': True, 'false': False}.get(final_grades.lower()) # convert parameter to boolean\n\n    form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, user=request.user)\n\n    if form.is_valid():\n        form.save()\n        if final_grades and course.state == 'reviewed':\n            course.publish()\n            course.save()\n            send_publish_notifications(grade_document_courses=[course], evaluation_results_courses=[course])\n        else:\n            send_publish_notifications(grade_document_courses=[course])            \n\n        messages.success(request, _(\"Successfully uploaded grades.\"))\n        return redirect('grades:course_view', semester.id, course.id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            form=form,\n            final_grades=final_grades,\n            show_automated_publishing_info=final_grades,\n        )\n        return render(request, \"grades_upload_form.html\", template_data)\n\n\n@grade_publisher_required\ndef toggle_no_grades(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n\n    if request.method == 'POST':\n        course.gets_no_grade_documents = not course.gets_no_grade_documents\n        course.save()\n        \n        if course.gets_no_grade_documents:\n            if course.state == 'reviewed':\n                course.publish()\n                course.save()\n                send_publish_notifications(evaluation_results_courses=[course])\n            messages.success(request, _(\"Successfully confirmed that no grade documents will be provided.\"))\n        else:\n            messages.success(request, _(\"Successfully confirmed that grade documents will be provided later on.\"))\n        return redirect('grades:semester_view', semester_id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n        )\n        return render(request, \"toggle_no_grades.html\", template_data)\n\n\n@grade_downloader_required\ndef download_grades(request, grade_document_id):\n    if not request.method == \"GET\":\n        return HttpResponseBadRequest()\n\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n    return sendfile(request, grade_document.file.path, attachment=True, attachment_filename=grade_document.filename())\n\n\n@grade_publisher_required\ndef edit_grades(request, semester_id, course_id, grade_document_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n    final_grades = grade_document.type == GradeDocument.FINAL_GRADES\n\n    form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, instance=grade_document, user=request.user)\n\n    if form.is_valid():\n        form.save()\n        messages.success(request, _(\"Successfully updated grades.\"))\n        return redirect('grades:course_view', semester.id, course.id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            form=form,\n            show_automated_publishing_info=False,\n        )\n        return render(request, \"grades_upload_form.html\", template_data)\n\n\n@grade_publisher_required\ndef delete_grades(request, semester_id, course_id, grade_document_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n\n    if request.method == 'POST':\n        grade_document.delete()\n        messages.success(request, _(\"Successfully deleted grade document.\"))\n        return redirect('grades:course_view', semester_id, course_id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            grade_document=grade_document,\n        )\n        return render(request, \"grades_delete.html\", template_data)\n", "path": "evap/grades/views.py"}], "after_files": [{"content": "from django.shortcuts import get_object_or_404, render, redirect\nfrom django.db.models import Prefetch\nfrom django.contrib import messages\nfrom django.utils.translation import ugettext as _\nfrom django.http import HttpResponseBadRequest, HttpResponseForbidden\n\nfrom sendfile import sendfile\n\nfrom evap.evaluation.auth import grade_publisher_required, grade_downloader_required, grade_publisher_or_staff_required\nfrom evap.evaluation.models import Semester, Contribution, Course\nfrom evap.grades.models import GradeDocument\nfrom evap.grades.forms import GradeDocumentForm\nfrom evap.evaluation.tools import send_publish_notifications\n\n\n@grade_publisher_required\ndef index(request):\n    template_data = dict(\n        semesters=Semester.objects.all()\n    )\n    return render(request, \"grades_index.html\", template_data)\n\n\ndef prefetch_data(courses):\n    courses = courses.prefetch_related(\n        Prefetch(\"contributions\", queryset=Contribution.objects.filter(responsible=True).select_related(\"contributor\"), to_attr=\"responsible_contribution\"),\n        \"degrees\")\n\n    course_data = []\n    for course in courses:\n        course.responsible_contributor = course.responsible_contribution[0].contributor\n        course_data.append((\n            course,\n            GradeDocument.objects.filter(course=course, type=GradeDocument.MIDTERM_GRADES).count(),\n            GradeDocument.objects.filter(course=course, type=GradeDocument.FINAL_GRADES).count()\n        ))\n\n    return course_data\n\n\n@grade_publisher_required\ndef semester_view(request, semester_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n\n    courses = semester.course_set.filter(is_graded=True).exclude(state='new')\n    courses = prefetch_data(courses)\n\n    template_data = dict(\n        semester=semester,\n        courses=courses,\n        disable_if_archived=\"disabled=disabled\" if semester.is_archived else \"\",\n        disable_breadcrumb_semester=True,\n    )\n    return render(request, \"grades_semester_view.html\", template_data)\n\n\n@grade_publisher_or_staff_required\ndef course_view(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    is_grade_publisher = request.user.is_grade_publisher\n\n    template_data = dict(\n        semester=semester,\n        course=course,\n        grade_documents=course.grade_documents.all(),\n        disable_if_archived=\"disabled=disabled\" if semester.is_archived else \"\",\n        disable_breadcrumb_course=True,\n        is_grade_publisher=is_grade_publisher,\n    )\n    return render(request, \"grades_course_view.html\", template_data)\n\n\n@grade_publisher_required\ndef upload_grades(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n\n    final_grades = request.GET.get('final', 'false') # default: midterm grades\n    final_grades = {'true': True, 'false': False}.get(final_grades.lower()) # convert parameter to boolean\n\n    form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, user=request.user)\n\n    if form.is_valid():\n        form.save()\n        if final_grades and course.state == 'reviewed':\n            course.publish()\n            course.save()\n            send_publish_notifications(grade_document_courses=[course], evaluation_results_courses=[course])\n        else:\n            send_publish_notifications(grade_document_courses=[course])            \n\n        messages.success(request, _(\"Successfully uploaded grades.\"))\n        return redirect('grades:course_view', semester.id, course.id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            form=form,\n            final_grades=final_grades,\n            show_automated_publishing_info=final_grades,\n        )\n        return render(request, \"grades_upload_form.html\", template_data)\n\n\n@grade_publisher_required\ndef toggle_no_grades(request, semester_id, course_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n\n    if request.method == 'POST':\n        course.gets_no_grade_documents = not course.gets_no_grade_documents\n        course.save()\n        \n        if course.gets_no_grade_documents:\n            if course.state == 'reviewed':\n                course.publish()\n                course.save()\n                send_publish_notifications(evaluation_results_courses=[course])\n            messages.success(request, _(\"Successfully confirmed that no grade documents will be provided.\"))\n        else:\n            messages.success(request, _(\"Successfully confirmed that grade documents will be provided later on.\"))\n        return redirect('grades:semester_view', semester_id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n        )\n        return render(request, \"toggle_no_grades.html\", template_data)\n\n\n@grade_downloader_required\ndef download_grades(request, grade_document_id):\n    if not request.method == \"GET\":\n        return HttpResponseBadRequest()\n\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n    return sendfile(request, grade_document.file.path, attachment=True, attachment_filename=grade_document.filename())\n\n\n@grade_publisher_required\ndef edit_grades(request, semester_id, course_id, grade_document_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n    final_grades = grade_document.type == GradeDocument.FINAL_GRADES\n\n    form = GradeDocumentForm(request.POST or None, request.FILES or None, course=course, final_grades=final_grades, instance=grade_document, user=request.user)\n\n    if form.is_valid():\n        form.save()\n        messages.success(request, _(\"Successfully updated grades.\"))\n        return redirect('grades:course_view', semester.id, course.id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            form=form,\n            show_automated_publishing_info=False,\n        )\n        return render(request, \"grades_upload_form.html\", template_data)\n\n\n@grade_publisher_required\ndef delete_grades(request, semester_id, course_id, grade_document_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    course = get_object_or_404(Course, id=course_id)\n    grade_document = get_object_or_404(GradeDocument, id=grade_document_id)\n\n    if request.method == 'POST':\n        grade_document.delete()\n        messages.success(request, _(\"Successfully deleted grade document.\"))\n        return redirect('grades:course_view', semester_id, course_id)\n    else:\n        template_data = dict(\n            semester=semester,\n            course=course,\n            grade_document=grade_document,\n        )\n        return render(request, \"grades_delete.html\", template_data)\n", "path": "evap/grades/views.py"}]}