We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Release Sisyphus data only after successful post
When a user enters answers on the student vote page and then logs out in another window before submitting the form, Sisyphus releases the form data on the form submit, because a 302 redirect to the login page is not an error case.
The data should be kept in browser storage until the vote was successfully counted.
Release Sisyphus data only after successful post
When a user enters answers on the student vote page and then logs out in another window before submitting the form, Sisyphus releases the form data on the form submit, because a 302 redirect to the login page is not an error case.
The data should be kept in browser storage until the vote was successfully counted.

--- 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/student/views.py`
Content:
```
1 from collections import OrderedDict
2 
3 from django.contrib import messages
4 from django.core.exceptions import PermissionDenied, SuspiciousOperation
5 from django.db import transaction
6 from django.shortcuts import get_object_or_404, redirect, render
7 from django.utils.translation import ugettext as _
8 
9 from evap.evaluation.auth import participant_required
10 from evap.evaluation.models import Course, Semester
11 from evap.evaluation.tools import STUDENT_STATES_ORDERED
12 
13 from evap.student.forms import QuestionsForm
14 from evap.student.tools import question_id
15 
16 
17 @participant_required
18 def index(request):
19     # retrieve all courses, where the user is a participant and that are not new
20     courses = list(set(Course.objects.filter(participants=request.user).exclude(state="new")))
21     voted_courses = list(set(Course.objects.filter(voters=request.user)))
22     due_courses = list(set(Course.objects.filter(participants=request.user, state='in_evaluation').exclude(voters=request.user)))
23 
24     sorter = lambda course: (list(STUDENT_STATES_ORDERED.keys()).index(course.student_state), course.vote_end_date, course.name)
25     courses.sort(key=sorter)
26 
27     semesters = Semester.objects.all()
28     semester_list = [dict(semester_name=semester.name, id=semester.id, is_active_semester=semester.is_active_semester,
29         courses=[course for course in courses if course.semester_id == semester.id]) for semester in semesters]
30 
31     template_data = dict(
32         semester_list=semester_list,
33         voted_courses=voted_courses,
34         due_courses=due_courses,
35         can_download_grades=request.user.can_download_grades,
36     )
37     return render(request, "student_index.html", template_data)
38 
39 
40 def vote_preview(request, course, for_rendering_in_modal=False):
41     """
42         Renders a preview of the voting page for the given course.
43         Not used by the student app itself, but by staff and contributor.
44     """
45     form_groups = helper_create_voting_form_groups(request, course.contributions.all())
46     course_form_group = form_groups.pop(course.general_contribution)
47     contributor_form_groups = list((contribution.contributor, contribution.label, form_group, False) for contribution, form_group in form_groups.items())
48 
49     template_data = dict(
50         errors_exist=False,
51         course_form_group=course_form_group,
52         contributor_form_groups=contributor_form_groups,
53         course=course,
54         preview=True,
55         for_rendering_in_modal=for_rendering_in_modal)
56     return render(request, "student_vote.html", template_data)
57 
58 
59 @participant_required
60 def vote(request, course_id):
61     # retrieve course and make sure that the user is allowed to vote
62     course = get_object_or_404(Course, id=course_id)
63     if not course.can_user_vote(request.user):
64         raise PermissionDenied
65 
66     
67     # prevent a user from voting on themselves.
68     contributions_to_vote_on = course.contributions.exclude(contributor=request.user).all()
69     form_groups = helper_create_voting_form_groups(request, contributions_to_vote_on)
70 
71     if not all(all(form.is_valid() for form in form_group) for form_group in form_groups.values()):
72         errors_exist = any(helper_has_errors(form_group) for form_group in form_groups.values())
73 
74         course_form_group = form_groups.pop(course.general_contribution)
75 
76         contributor_form_groups = list((contribution.contributor, contribution.label, form_group, helper_has_errors(form_group)) for contribution, form_group in form_groups.items())
77 
78         template_data = dict(
79             errors_exist=errors_exist,
80             course_form_group=course_form_group,
81             contributor_form_groups=contributor_form_groups,
82             course=course,
83             participants_warning=course.num_participants <= 5,
84             preview=False,
85             vote_end_datetime=course.vote_end_datetime,
86             hours_left_for_evaluation=course.time_left_for_evaluation.seconds//3600,
87             minutes_left_for_evaluation=(course.time_left_for_evaluation.seconds//60)%60,
88             evaluation_ends_soon=course.evaluation_ends_soon())
89         return render(request, "student_vote.html", template_data)
90 
91     # all forms are valid, begin vote operation
92     with transaction.atomic():
93         # add user to course.voters
94         # not using course.voters.add(request.user) since it fails silently when done twice.
95         # manually inserting like this gives us the 'created' return value and ensures at the database level that nobody votes twice.
96         __, created = course.voters.through.objects.get_or_create(userprofile_id=request.user.pk, course_id=course.pk)
97         if not created:  # vote already got recorded, bail out
98             raise SuspiciousOperation("A second vote has been received shortly after the first one.")
99 
100         for contribution, form_group in form_groups.items():
101             for questionnaire_form in form_group:
102                 questionnaire = questionnaire_form.questionnaire
103                 for question in questionnaire.question_set.all():
104                     identifier = question_id(contribution, questionnaire, question)
105                     value = questionnaire_form.cleaned_data.get(identifier)
106 
107                     if question.is_text_question:
108                         if value:
109                             question.answer_class.objects.create(
110                                 contribution=contribution,
111                                 question=question,
112                                 answer=value)
113                     elif question.is_heading_question:
114                         pass  # ignore these
115                     else:
116                         if value != 6:
117                             answer_counter, __ = question.answer_class.objects.get_or_create(contribution=contribution, question=question, answer=value)
118                             answer_counter.add_vote()
119                             answer_counter.save()
120 
121         course.course_evaluated.send(sender=Course, request=request, semester=course.semester)
122 
123     messages.success(request, _("Your vote was recorded."))
124     return redirect('student:index')
125 
126 
127 def helper_create_voting_form_groups(request, contributions):
128     form_groups = OrderedDict()
129     for contribution in contributions:
130         questionnaires = contribution.questionnaires.all()
131         if not questionnaires.exists():
132             continue
133         form_groups[contribution] = [QuestionsForm(request.POST or None, contribution=contribution, questionnaire=questionnaire) for questionnaire in questionnaires]
134     return form_groups
135 
136 
137 def helper_has_errors(form_group):
138     return any(form.errors for form in form_group)
139
```
--- 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/student/views.py b/evap/student/views.py
--- a/evap/student/views.py
+++ b/evap/student/views.py
@@ -3,7 +3,9 @@
 from django.contrib import messages
 from django.core.exceptions import PermissionDenied, SuspiciousOperation
 from django.db import transaction
+from django.http import HttpResponse
 from django.shortcuts import get_object_or_404, redirect, render
+from django.urls import reverse
 from django.utils.translation import ugettext as _
 
 from evap.evaluation.auth import participant_required
@@ -13,6 +15,7 @@
 from evap.student.forms import QuestionsForm
 from evap.student.tools import question_id
 
+SUCCESS_MAGIC_STRING = 'vote submitted successfully'
 
 @participant_required
 def index(request):
@@ -58,12 +61,11 @@
 
 @participant_required
 def vote(request, course_id):
-    # retrieve course and make sure that the user is allowed to vote
+
     course = get_object_or_404(Course, id=course_id)
     if not course.can_user_vote(request.user):
         raise PermissionDenied
 
-    
     # prevent a user from voting on themselves.
     contributions_to_vote_on = course.contributions.exclude(contributor=request.user).all()
     form_groups = helper_create_voting_form_groups(request, contributions_to_vote_on)
@@ -85,6 +87,8 @@
             vote_end_datetime=course.vote_end_datetime,
             hours_left_for_evaluation=course.time_left_for_evaluation.seconds//3600,
             minutes_left_for_evaluation=(course.time_left_for_evaluation.seconds//60)%60,
+            success_magic_string=SUCCESS_MAGIC_STRING,
+            success_redirect_url=reverse('student:index'),
             evaluation_ends_soon=course.evaluation_ends_soon())
         return render(request, "student_vote.html", template_data)
 
@@ -121,7 +125,7 @@
         course.course_evaluated.send(sender=Course, request=request, semester=course.semester)
 
     messages.success(request, _("Your vote was recorded."))
-    return redirect('student:index')
+    return HttpResponse(SUCCESS_MAGIC_STRING)
 
 
 def helper_create_voting_form_groups(request, contributions):

{"golden_diff": "diff --git a/evap/student/views.py b/evap/student/views.py\n--- a/evap/student/views.py\n+++ b/evap/student/views.py\n@@ -3,7 +3,9 @@\n from django.contrib import messages\n from django.core.exceptions import PermissionDenied, SuspiciousOperation\n from django.db import transaction\n+from django.http import HttpResponse\n from django.shortcuts import get_object_or_404, redirect, render\n+from django.urls import reverse\n from django.utils.translation import ugettext as _\n \n from evap.evaluation.auth import participant_required\n@@ -13,6 +15,7 @@\n from evap.student.forms import QuestionsForm\n from evap.student.tools import question_id\n \n+SUCCESS_MAGIC_STRING = 'vote submitted successfully'\n \n @participant_required\n def index(request):\n@@ -58,12 +61,11 @@\n \n @participant_required\n def vote(request, course_id):\n-    # retrieve course and make sure that the user is allowed to vote\n+\n     course = get_object_or_404(Course, id=course_id)\n     if not course.can_user_vote(request.user):\n         raise PermissionDenied\n \n-    \n     # prevent a user from voting on themselves.\n     contributions_to_vote_on = course.contributions.exclude(contributor=request.user).all()\n     form_groups = helper_create_voting_form_groups(request, contributions_to_vote_on)\n@@ -85,6 +87,8 @@\n             vote_end_datetime=course.vote_end_datetime,\n             hours_left_for_evaluation=course.time_left_for_evaluation.seconds//3600,\n             minutes_left_for_evaluation=(course.time_left_for_evaluation.seconds//60)%60,\n+            success_magic_string=SUCCESS_MAGIC_STRING,\n+            success_redirect_url=reverse('student:index'),\n             evaluation_ends_soon=course.evaluation_ends_soon())\n         return render(request, \"student_vote.html\", template_data)\n \n@@ -121,7 +125,7 @@\n         course.course_evaluated.send(sender=Course, request=request, semester=course.semester)\n \n     messages.success(request, _(\"Your vote was recorded.\"))\n-    return redirect('student:index')\n+    return HttpResponse(SUCCESS_MAGIC_STRING)\n \n \n def helper_create_voting_form_groups(request, contributions):\n", "issue": "Release Sisyphus data only after successful post\nWhen a user enters answers on the student vote page and then logs out in another window before submitting the form, Sisyphus releases the form data on the form submit, because a 302 redirect to the login page is not an error case.\r\nThe data should be kept in browser storage until the vote was successfully counted.\nRelease Sisyphus data only after successful post\nWhen a user enters answers on the student vote page and then logs out in another window before submitting the form, Sisyphus releases the form data on the form submit, because a 302 redirect to the login page is not an error case.\r\nThe data should be kept in browser storage until the vote was successfully counted.\n", "before_files": [{"content": "from collections import OrderedDict\n\nfrom django.contrib import messages\nfrom django.core.exceptions import PermissionDenied, SuspiciousOperation\nfrom django.db import transaction\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils.translation import ugettext as _\n\nfrom evap.evaluation.auth import participant_required\nfrom evap.evaluation.models import Course, Semester\nfrom evap.evaluation.tools import STUDENT_STATES_ORDERED\n\nfrom evap.student.forms import QuestionsForm\nfrom evap.student.tools import question_id\n\n\n@participant_required\ndef index(request):\n    # retrieve all courses, where the user is a participant and that are not new\n    courses = list(set(Course.objects.filter(participants=request.user).exclude(state=\"new\")))\n    voted_courses = list(set(Course.objects.filter(voters=request.user)))\n    due_courses = list(set(Course.objects.filter(participants=request.user, state='in_evaluation').exclude(voters=request.user)))\n\n    sorter = lambda course: (list(STUDENT_STATES_ORDERED.keys()).index(course.student_state), course.vote_end_date, course.name)\n    courses.sort(key=sorter)\n\n    semesters = Semester.objects.all()\n    semester_list = [dict(semester_name=semester.name, id=semester.id, is_active_semester=semester.is_active_semester,\n        courses=[course for course in courses if course.semester_id == semester.id]) for semester in semesters]\n\n    template_data = dict(\n        semester_list=semester_list,\n        voted_courses=voted_courses,\n        due_courses=due_courses,\n        can_download_grades=request.user.can_download_grades,\n    )\n    return render(request, \"student_index.html\", template_data)\n\n\ndef vote_preview(request, course, for_rendering_in_modal=False):\n    \"\"\"\n        Renders a preview of the voting page for the given course.\n        Not used by the student app itself, but by staff and contributor.\n    \"\"\"\n    form_groups = helper_create_voting_form_groups(request, course.contributions.all())\n    course_form_group = form_groups.pop(course.general_contribution)\n    contributor_form_groups = list((contribution.contributor, contribution.label, form_group, False) for contribution, form_group in form_groups.items())\n\n    template_data = dict(\n        errors_exist=False,\n        course_form_group=course_form_group,\n        contributor_form_groups=contributor_form_groups,\n        course=course,\n        preview=True,\n        for_rendering_in_modal=for_rendering_in_modal)\n    return render(request, \"student_vote.html\", template_data)\n\n\n@participant_required\ndef vote(request, course_id):\n    # retrieve course and make sure that the user is allowed to vote\n    course = get_object_or_404(Course, id=course_id)\n    if not course.can_user_vote(request.user):\n        raise PermissionDenied\n\n    \n    # prevent a user from voting on themselves.\n    contributions_to_vote_on = course.contributions.exclude(contributor=request.user).all()\n    form_groups = helper_create_voting_form_groups(request, contributions_to_vote_on)\n\n    if not all(all(form.is_valid() for form in form_group) for form_group in form_groups.values()):\n        errors_exist = any(helper_has_errors(form_group) for form_group in form_groups.values())\n\n        course_form_group = form_groups.pop(course.general_contribution)\n\n        contributor_form_groups = list((contribution.contributor, contribution.label, form_group, helper_has_errors(form_group)) for contribution, form_group in form_groups.items())\n\n        template_data = dict(\n            errors_exist=errors_exist,\n            course_form_group=course_form_group,\n            contributor_form_groups=contributor_form_groups,\n            course=course,\n            participants_warning=course.num_participants <= 5,\n            preview=False,\n            vote_end_datetime=course.vote_end_datetime,\n            hours_left_for_evaluation=course.time_left_for_evaluation.seconds//3600,\n            minutes_left_for_evaluation=(course.time_left_for_evaluation.seconds//60)%60,\n            evaluation_ends_soon=course.evaluation_ends_soon())\n        return render(request, \"student_vote.html\", template_data)\n\n    # all forms are valid, begin vote operation\n    with transaction.atomic():\n        # add user to course.voters\n        # not using course.voters.add(request.user) since it fails silently when done twice.\n        # manually inserting like this gives us the 'created' return value and ensures at the database level that nobody votes twice.\n        __, created = course.voters.through.objects.get_or_create(userprofile_id=request.user.pk, course_id=course.pk)\n        if not created:  # vote already got recorded, bail out\n            raise SuspiciousOperation(\"A second vote has been received shortly after the first one.\")\n\n        for contribution, form_group in form_groups.items():\n            for questionnaire_form in form_group:\n                questionnaire = questionnaire_form.questionnaire\n                for question in questionnaire.question_set.all():\n                    identifier = question_id(contribution, questionnaire, question)\n                    value = questionnaire_form.cleaned_data.get(identifier)\n\n                    if question.is_text_question:\n                        if value:\n                            question.answer_class.objects.create(\n                                contribution=contribution,\n                                question=question,\n                                answer=value)\n                    elif question.is_heading_question:\n                        pass  # ignore these\n                    else:\n                        if value != 6:\n                            answer_counter, __ = question.answer_class.objects.get_or_create(contribution=contribution, question=question, answer=value)\n                            answer_counter.add_vote()\n                            answer_counter.save()\n\n        course.course_evaluated.send(sender=Course, request=request, semester=course.semester)\n\n    messages.success(request, _(\"Your vote was recorded.\"))\n    return redirect('student:index')\n\n\ndef helper_create_voting_form_groups(request, contributions):\n    form_groups = OrderedDict()\n    for contribution in contributions:\n        questionnaires = contribution.questionnaires.all()\n        if not questionnaires.exists():\n            continue\n        form_groups[contribution] = [QuestionsForm(request.POST or None, contribution=contribution, questionnaire=questionnaire) for questionnaire in questionnaires]\n    return form_groups\n\n\ndef helper_has_errors(form_group):\n    return any(form.errors for form in form_group)\n", "path": "evap/student/views.py"}], "after_files": [{"content": "from collections import OrderedDict\n\nfrom django.contrib import messages\nfrom django.core.exceptions import PermissionDenied, SuspiciousOperation\nfrom django.db import transaction\nfrom django.http import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.urls import reverse\nfrom django.utils.translation import ugettext as _\n\nfrom evap.evaluation.auth import participant_required\nfrom evap.evaluation.models import Course, Semester\nfrom evap.evaluation.tools import STUDENT_STATES_ORDERED\n\nfrom evap.student.forms import QuestionsForm\nfrom evap.student.tools import question_id\n\nSUCCESS_MAGIC_STRING = 'vote submitted successfully'\n\n@participant_required\ndef index(request):\n    # retrieve all courses, where the user is a participant and that are not new\n    courses = list(set(Course.objects.filter(participants=request.user).exclude(state=\"new\")))\n    voted_courses = list(set(Course.objects.filter(voters=request.user)))\n    due_courses = list(set(Course.objects.filter(participants=request.user, state='in_evaluation').exclude(voters=request.user)))\n\n    sorter = lambda course: (list(STUDENT_STATES_ORDERED.keys()).index(course.student_state), course.vote_end_date, course.name)\n    courses.sort(key=sorter)\n\n    semesters = Semester.objects.all()\n    semester_list = [dict(semester_name=semester.name, id=semester.id, is_active_semester=semester.is_active_semester,\n        courses=[course for course in courses if course.semester_id == semester.id]) for semester in semesters]\n\n    template_data = dict(\n        semester_list=semester_list,\n        voted_courses=voted_courses,\n        due_courses=due_courses,\n        can_download_grades=request.user.can_download_grades,\n    )\n    return render(request, \"student_index.html\", template_data)\n\n\ndef vote_preview(request, course, for_rendering_in_modal=False):\n    \"\"\"\n        Renders a preview of the voting page for the given course.\n        Not used by the student app itself, but by staff and contributor.\n    \"\"\"\n    form_groups = helper_create_voting_form_groups(request, course.contributions.all())\n    course_form_group = form_groups.pop(course.general_contribution)\n    contributor_form_groups = list((contribution.contributor, contribution.label, form_group, False) for contribution, form_group in form_groups.items())\n\n    template_data = dict(\n        errors_exist=False,\n        course_form_group=course_form_group,\n        contributor_form_groups=contributor_form_groups,\n        course=course,\n        preview=True,\n        for_rendering_in_modal=for_rendering_in_modal)\n    return render(request, \"student_vote.html\", template_data)\n\n\n@participant_required\ndef vote(request, course_id):\n\n    course = get_object_or_404(Course, id=course_id)\n    if not course.can_user_vote(request.user):\n        raise PermissionDenied\n\n    # prevent a user from voting on themselves.\n    contributions_to_vote_on = course.contributions.exclude(contributor=request.user).all()\n    form_groups = helper_create_voting_form_groups(request, contributions_to_vote_on)\n\n    if not all(all(form.is_valid() for form in form_group) for form_group in form_groups.values()):\n        errors_exist = any(helper_has_errors(form_group) for form_group in form_groups.values())\n\n        course_form_group = form_groups.pop(course.general_contribution)\n\n        contributor_form_groups = list((contribution.contributor, contribution.label, form_group, helper_has_errors(form_group)) for contribution, form_group in form_groups.items())\n\n        template_data = dict(\n            errors_exist=errors_exist,\n            course_form_group=course_form_group,\n            contributor_form_groups=contributor_form_groups,\n            course=course,\n            participants_warning=course.num_participants <= 5,\n            preview=False,\n            vote_end_datetime=course.vote_end_datetime,\n            hours_left_for_evaluation=course.time_left_for_evaluation.seconds//3600,\n            minutes_left_for_evaluation=(course.time_left_for_evaluation.seconds//60)%60,\n            success_magic_string=SUCCESS_MAGIC_STRING,\n            success_redirect_url=reverse('student:index'),\n            evaluation_ends_soon=course.evaluation_ends_soon())\n        return render(request, \"student_vote.html\", template_data)\n\n    # all forms are valid, begin vote operation\n    with transaction.atomic():\n        # add user to course.voters\n        # not using course.voters.add(request.user) since it fails silently when done twice.\n        # manually inserting like this gives us the 'created' return value and ensures at the database level that nobody votes twice.\n        __, created = course.voters.through.objects.get_or_create(userprofile_id=request.user.pk, course_id=course.pk)\n        if not created:  # vote already got recorded, bail out\n            raise SuspiciousOperation(\"A second vote has been received shortly after the first one.\")\n\n        for contribution, form_group in form_groups.items():\n            for questionnaire_form in form_group:\n                questionnaire = questionnaire_form.questionnaire\n                for question in questionnaire.question_set.all():\n                    identifier = question_id(contribution, questionnaire, question)\n                    value = questionnaire_form.cleaned_data.get(identifier)\n\n                    if question.is_text_question:\n                        if value:\n                            question.answer_class.objects.create(\n                                contribution=contribution,\n                                question=question,\n                                answer=value)\n                    elif question.is_heading_question:\n                        pass  # ignore these\n                    else:\n                        if value != 6:\n                            answer_counter, __ = question.answer_class.objects.get_or_create(contribution=contribution, question=question, answer=value)\n                            answer_counter.add_vote()\n                            answer_counter.save()\n\n        course.course_evaluated.send(sender=Course, request=request, semester=course.semester)\n\n    messages.success(request, _(\"Your vote was recorded.\"))\n    return HttpResponse(SUCCESS_MAGIC_STRING)\n\n\ndef helper_create_voting_form_groups(request, contributions):\n    form_groups = OrderedDict()\n    for contribution in contributions:\n        questionnaires = contribution.questionnaires.all()\n        if not questionnaires.exists():\n            continue\n        form_groups[contribution] = [QuestionsForm(request.POST or None, contribution=contribution, questionnaire=questionnaire) for questionnaire in questionnaires]\n    return form_groups\n\n\ndef helper_has_errors(form_group):\n    return any(form.errors for form in form_group)\n", "path": "evap/student/views.py"}]}