We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
automatic notification for user about arriving on pages of a past course
A+ knows that a course has closed since course instances have opening and closing times. Any closed course instance could show a warning easily. Adding an automatic link to the newest course instance would be easy too.

[Teacher needs spring 2020](https://wiki.aalto.fi/display/EDIT/Teacher+needs+spring+2020): nr 12

To be allocated to one of the summer interns

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `course/views.py`
Content:
```
1 import datetime
2 
3 import icalendar
4 from django.conf import settings
5 from django.contrib import messages
6 from django.core.exceptions import PermissionDenied
7 from django.http import Http404
8 from django.http.response import HttpResponse
9 from django.shortcuts import get_object_or_404, redirect
10 from django.utils import html
11 from django.utils import timezone
12 from django.utils.translation import ugettext_lazy as _
13 
14 from authorization.permissions import ACCESS
15 from exercise.cache.hierarchy import NoSuchContent
16 from exercise.models import LearningObject
17 from lib.helpers import settings_text
18 from lib.viewbase import BaseTemplateView, BaseRedirectMixin, BaseFormView, BaseView
19 from userprofile.viewbase import UserProfileView
20 from .forms import GroupsForm, GroupSelectForm
21 from .models import CourseInstance, Enrollment
22 from .permissions import EnrollInfoVisiblePermission
23 from .renders import group_info_context
24 from .viewbase import CourseModuleBaseView, CourseInstanceMixin, EnrollableViewMixin
25 
26 
27 class HomeView(UserProfileView):
28     access_mode = ACCESS.ANONYMOUS
29     template_name = "course/index.html"
30 
31     def get_common_objects(self):
32         super().get_common_objects()
33         self.welcome_text = settings_text('WELCOME_TEXT')
34         self.internal_user_label = settings_text('INTERNAL_USER_LABEL')
35         self.external_user_label = settings_text('EXTERNAL_USER_LABEL')
36         my_instances = []
37         all_instances = []
38         end_threshold = timezone.now() - datetime.timedelta(days=30)
39         user = self.request.user
40         is_logged_in = False
41 
42         if user and user.is_authenticated:
43             is_logged_in = True
44             for instance in (CourseInstance.objects
45                 .filter(course__teachers=user.userprofile,
46                         ending_time__gte=end_threshold)
47                 .all()):
48                 my_instances.append(instance)
49 
50             for instance in user.userprofile.assisting_courses.all().filter(ending_time__gte=end_threshold):
51                 if instance not in my_instances:
52                     my_instances.append(instance)
53             
54             for instance in user.userprofile.enrolled.all().filter(ending_time__gte=end_threshold):
55                 if instance not in my_instances:
56                     my_instances.append(instance)
57         
58         all_instances = CourseInstance.objects.get_visible(user).filter(ending_time__gte=end_threshold)
59         all_instances = [c for c in all_instances if c not in my_instances]
60         
61         self.all_instances = all_instances
62         self.my_instances = my_instances
63         self.is_logged_in = is_logged_in
64 
65         self.note("welcome_text", 
66             "internal_user_label", 
67             "external_user_label",
68             "my_instances",
69             "all_instances",
70             "is_logged_in",
71         )
72 
73 
74 class ArchiveView(UserProfileView):
75     access_mode = ACCESS.ANONYMOUS
76     template_name = "course/archive.html"
77 
78     def get_common_objects(self):
79         super().get_common_objects()
80         self.instances = CourseInstance.objects.get_visible(self.request.user)
81         self.note("instances")
82 
83 class InstanceView(EnrollableViewMixin, BaseTemplateView):
84     access_mode = ACCESS.STUDENT
85     # ACCESS.STUDENT requires users to log in, but the access mode is dropped
86     # in public courses. CourseVisiblePermission has more restrictions as well.
87     template_name = "course/course.html"
88 
89     def handle_no_permission(self):
90         if self.request.user.is_authenticated \
91                 and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED:
92             # The course instance is visible to only enrolled students, so
93             # redirect the user to the enroll page instead of showing
94             # a 403 Forbidden error.
95             return redirect(self.instance.get_url('enroll'))
96         return super().handle_no_permission()
97 
98     def get(self, request, *args, **kwargs):
99         # external LTI Tool Providers may return the user to the course instance view
100         # with a message given in GET query parameters
101         lti_error_msg = request.GET.get('lti_errormsg')
102         lti_msg = request.GET.get('lti_msg')
103         # message HTML is not escaped in the templates so escape it here
104         if lti_error_msg:
105             messages.error(request, html.escape(lti_error_msg))
106         elif lti_msg:
107             messages.info(request, html.escape(lti_msg))
108 
109         return super().get(request, *args, **kwargs)
110 
111 
112 class Enroll(EnrollableViewMixin, BaseRedirectMixin, BaseTemplateView):
113     permission_classes = [EnrollInfoVisiblePermission]
114     course_permission_classes = []
115     template_name = "course/enroll.html"
116 
117     def post(self, request, *args, **kwargs):
118 
119         if self.is_student or not self.enrollable:
120             messages.error(self.request, _("You cannot enroll, or have already enrolled, in this course."))
121             raise PermissionDenied()
122 
123         if not self.instance.is_enrollment_open():
124             messages.error(self.request, _("The enrollment is not open."))
125             raise PermissionDenied()
126 
127         # Support enrollment questionnaires.
128         exercise = LearningObject.objects.find_enrollment_exercise(
129             self.instance, self.profile)
130         if exercise:
131             return self.redirect(exercise.get_absolute_url())
132 
133         self.instance.enroll_student(self.request.user)
134         return self.redirect(self.instance.get_absolute_url())
135 
136 
137 class ModuleView(CourseModuleBaseView):
138     template_name = "course/module.html"
139 
140     def get_common_objects(self):
141         super().get_common_objects()
142         self.now = timezone.now()
143         try:
144             self.children = self.content.flat_module(self.module)
145             cur, tree, prev, nex = self.content.find(self.module)
146             self.previous = prev
147             self.current = cur
148             self.next = nex
149         except NoSuchContent:
150             raise Http404
151         self.note('now', 'children', 'previous', 'current', 'next')
152 
153 
154 class CalendarExport(CourseInstanceMixin, BaseView):
155 
156     def get(self, request, *args, **kwargs):
157         cal = icalendar.Calendar()
158         cal.add('prodid', '-// {} calendar //'.format(settings.BRAND_NAME))
159         cal.add('version', '2.0')
160         for module in self.instance.course_modules.all():
161             event = icalendar.Event()
162             event.add('summary', module.name)
163             event.add('dtstart',
164                 module.closing_time - datetime.timedelta(hours=1))
165             event.add('dtend', module.closing_time)
166             event.add('dtstamp', module.closing_time)
167             event['uid'] = "module/" + str(module.id) + "/A+"
168             cal.add_component(event)
169 
170         return HttpResponse(cal.to_ical(),
171             content_type="text/calendar; charset=utf-8")
172 
173 
174 class GroupsView(CourseInstanceMixin, BaseFormView):
175     access_mode = ACCESS.ENROLLED
176     template_name = "course/groups.html"
177     form_class = GroupsForm
178 
179     def get_common_objects(self):
180         super().get_common_objects()
181         self.enrollment = self.instance.get_enrollment_for(self.request.user)
182         self.groups = list(self.profile.groups.filter(course_instance=self.instance))
183         self.note('enrollment','groups')
184 
185     def get_form_kwargs(self):
186         kwargs = super().get_form_kwargs()
187         kwargs["profile"] = self.profile
188         kwargs["instance"] = self.instance
189         kwargs["content"] = self.content
190         return kwargs
191 
192     def get_success_url(self):
193         return self.instance.get_url('groups')
194 
195     def form_valid(self, form):
196         form.save()
197         messages.success(self.request, _("A new student group was created."))
198         return super().form_valid(form)
199 
200 
201 class GroupSelect(CourseInstanceMixin, BaseFormView):
202     access_mode = ACCESS.ENROLLED
203     form_class = GroupSelectForm
204     template_name = "course/_group_info.html"
205 
206     def get_form_kwargs(self):
207         kwargs = super().get_form_kwargs()
208         kwargs["profile"] = self.profile
209         kwargs["instance"] = self.instance
210         return kwargs
211 
212     def get_success_url(self):
213         return self.instance.get_absolute_url()
214 
215     def get(self, request, *args, **kwargs):
216         return self.http_method_not_allowed(request, *args, **kwargs)
217 
218     def form_invalid(self, form):
219         return HttpResponse('Invalid group selection')
220 
221     def form_valid(self, form):
222         enrollment = form.save()
223         if self.request.is_ajax():
224             return self.render_to_response(self.get_context_data(
225                 **group_info_context(enrollment.selected_group, self.profile)))
226         return super().form_valid(form)
227
```
--- 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/course/views.py b/course/views.py
--- a/course/views.py
+++ b/course/views.py
@@ -106,8 +106,22 @@
         elif lti_msg:
             messages.info(request, html.escape(lti_msg))
 
-        return super().get(request, *args, **kwargs)
+        later_instance = None
+
+        if self.instance.is_past:
+            try:
+                later_instance = (
+                    CourseInstance.objects
+                        .get_visible(request.user)
+                        .filter(course=self.course, ending_time__gte=timezone.now())
+                        .latest('starting_time')
+                )
+            except CourseInstance.DoesNotExist:
+                pass
 
+        kwargs['later_instance'] = later_instance
+
+        return super().get(request, *args, **kwargs)
 
 class Enroll(EnrollableViewMixin, BaseRedirectMixin, BaseTemplateView):
     permission_classes = [EnrollInfoVisiblePermission]

{"golden_diff": "diff --git a/course/views.py b/course/views.py\n--- a/course/views.py\n+++ b/course/views.py\n@@ -106,8 +106,22 @@\n         elif lti_msg:\n             messages.info(request, html.escape(lti_msg))\n \n-        return super().get(request, *args, **kwargs)\n+        later_instance = None\n+\n+        if self.instance.is_past:\n+            try:\n+                later_instance = (\n+                    CourseInstance.objects\n+                        .get_visible(request.user)\n+                        .filter(course=self.course, ending_time__gte=timezone.now())\n+                        .latest('starting_time')\n+                )\n+            except CourseInstance.DoesNotExist:\n+                pass\n \n+        kwargs['later_instance'] = later_instance\n+\n+        return super().get(request, *args, **kwargs)\n \n class Enroll(EnrollableViewMixin, BaseRedirectMixin, BaseTemplateView):\n     permission_classes = [EnrollInfoVisiblePermission]\n", "issue": "automatic notification for user about arriving on pages of a past course\nA+ knows that a course has closed since course instances have opening and closing times. Any closed course instance could show a warning easily. Adding an automatic link to the newest course instance would be easy too.\r\n\r\n[Teacher needs spring 2020](https://wiki.aalto.fi/display/EDIT/Teacher+needs+spring+2020): nr 12\r\n\r\nTo be allocated to one of the summer interns\n", "before_files": [{"content": "import datetime\n\nimport icalendar\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404\nfrom django.http.response import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import html\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom authorization.permissions import ACCESS\nfrom exercise.cache.hierarchy import NoSuchContent\nfrom exercise.models import LearningObject\nfrom lib.helpers import settings_text\nfrom lib.viewbase import BaseTemplateView, BaseRedirectMixin, BaseFormView, BaseView\nfrom userprofile.viewbase import UserProfileView\nfrom .forms import GroupsForm, GroupSelectForm\nfrom .models import CourseInstance, Enrollment\nfrom .permissions import EnrollInfoVisiblePermission\nfrom .renders import group_info_context\nfrom .viewbase import CourseModuleBaseView, CourseInstanceMixin, EnrollableViewMixin\n\n\nclass HomeView(UserProfileView):\n    access_mode = ACCESS.ANONYMOUS\n    template_name = \"course/index.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.welcome_text = settings_text('WELCOME_TEXT')\n        self.internal_user_label = settings_text('INTERNAL_USER_LABEL')\n        self.external_user_label = settings_text('EXTERNAL_USER_LABEL')\n        my_instances = []\n        all_instances = []\n        end_threshold = timezone.now() - datetime.timedelta(days=30)\n        user = self.request.user\n        is_logged_in = False\n\n        if user and user.is_authenticated:\n            is_logged_in = True\n            for instance in (CourseInstance.objects\n                .filter(course__teachers=user.userprofile,\n                        ending_time__gte=end_threshold)\n                .all()):\n                my_instances.append(instance)\n\n            for instance in user.userprofile.assisting_courses.all().filter(ending_time__gte=end_threshold):\n                if instance not in my_instances:\n                    my_instances.append(instance)\n            \n            for instance in user.userprofile.enrolled.all().filter(ending_time__gte=end_threshold):\n                if instance not in my_instances:\n                    my_instances.append(instance)\n        \n        all_instances = CourseInstance.objects.get_visible(user).filter(ending_time__gte=end_threshold)\n        all_instances = [c for c in all_instances if c not in my_instances]\n        \n        self.all_instances = all_instances\n        self.my_instances = my_instances\n        self.is_logged_in = is_logged_in\n\n        self.note(\"welcome_text\", \n            \"internal_user_label\", \n            \"external_user_label\",\n            \"my_instances\",\n            \"all_instances\",\n            \"is_logged_in\",\n        )\n\n\nclass ArchiveView(UserProfileView):\n    access_mode = ACCESS.ANONYMOUS\n    template_name = \"course/archive.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.instances = CourseInstance.objects.get_visible(self.request.user)\n        self.note(\"instances\")\n\nclass InstanceView(EnrollableViewMixin, BaseTemplateView):\n    access_mode = ACCESS.STUDENT\n    # ACCESS.STUDENT requires users to log in, but the access mode is dropped\n    # in public courses. CourseVisiblePermission has more restrictions as well.\n    template_name = \"course/course.html\"\n\n    def handle_no_permission(self):\n        if self.request.user.is_authenticated \\\n                and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED:\n            # The course instance is visible to only enrolled students, so\n            # redirect the user to the enroll page instead of showing\n            # a 403 Forbidden error.\n            return redirect(self.instance.get_url('enroll'))\n        return super().handle_no_permission()\n\n    def get(self, request, *args, **kwargs):\n        # external LTI Tool Providers may return the user to the course instance view\n        # with a message given in GET query parameters\n        lti_error_msg = request.GET.get('lti_errormsg')\n        lti_msg = request.GET.get('lti_msg')\n        # message HTML is not escaped in the templates so escape it here\n        if lti_error_msg:\n            messages.error(request, html.escape(lti_error_msg))\n        elif lti_msg:\n            messages.info(request, html.escape(lti_msg))\n\n        return super().get(request, *args, **kwargs)\n\n\nclass Enroll(EnrollableViewMixin, BaseRedirectMixin, BaseTemplateView):\n    permission_classes = [EnrollInfoVisiblePermission]\n    course_permission_classes = []\n    template_name = \"course/enroll.html\"\n\n    def post(self, request, *args, **kwargs):\n\n        if self.is_student or not self.enrollable:\n            messages.error(self.request, _(\"You cannot enroll, or have already enrolled, in this course.\"))\n            raise PermissionDenied()\n\n        if not self.instance.is_enrollment_open():\n            messages.error(self.request, _(\"The enrollment is not open.\"))\n            raise PermissionDenied()\n\n        # Support enrollment questionnaires.\n        exercise = LearningObject.objects.find_enrollment_exercise(\n            self.instance, self.profile)\n        if exercise:\n            return self.redirect(exercise.get_absolute_url())\n\n        self.instance.enroll_student(self.request.user)\n        return self.redirect(self.instance.get_absolute_url())\n\n\nclass ModuleView(CourseModuleBaseView):\n    template_name = \"course/module.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.now = timezone.now()\n        try:\n            self.children = self.content.flat_module(self.module)\n            cur, tree, prev, nex = self.content.find(self.module)\n            self.previous = prev\n            self.current = cur\n            self.next = nex\n        except NoSuchContent:\n            raise Http404\n        self.note('now', 'children', 'previous', 'current', 'next')\n\n\nclass CalendarExport(CourseInstanceMixin, BaseView):\n\n    def get(self, request, *args, **kwargs):\n        cal = icalendar.Calendar()\n        cal.add('prodid', '-// {} calendar //'.format(settings.BRAND_NAME))\n        cal.add('version', '2.0')\n        for module in self.instance.course_modules.all():\n            event = icalendar.Event()\n            event.add('summary', module.name)\n            event.add('dtstart',\n                module.closing_time - datetime.timedelta(hours=1))\n            event.add('dtend', module.closing_time)\n            event.add('dtstamp', module.closing_time)\n            event['uid'] = \"module/\" + str(module.id) + \"/A+\"\n            cal.add_component(event)\n\n        return HttpResponse(cal.to_ical(),\n            content_type=\"text/calendar; charset=utf-8\")\n\n\nclass GroupsView(CourseInstanceMixin, BaseFormView):\n    access_mode = ACCESS.ENROLLED\n    template_name = \"course/groups.html\"\n    form_class = GroupsForm\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.enrollment = self.instance.get_enrollment_for(self.request.user)\n        self.groups = list(self.profile.groups.filter(course_instance=self.instance))\n        self.note('enrollment','groups')\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"profile\"] = self.profile\n        kwargs[\"instance\"] = self.instance\n        kwargs[\"content\"] = self.content\n        return kwargs\n\n    def get_success_url(self):\n        return self.instance.get_url('groups')\n\n    def form_valid(self, form):\n        form.save()\n        messages.success(self.request, _(\"A new student group was created.\"))\n        return super().form_valid(form)\n\n\nclass GroupSelect(CourseInstanceMixin, BaseFormView):\n    access_mode = ACCESS.ENROLLED\n    form_class = GroupSelectForm\n    template_name = \"course/_group_info.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"profile\"] = self.profile\n        kwargs[\"instance\"] = self.instance\n        return kwargs\n\n    def get_success_url(self):\n        return self.instance.get_absolute_url()\n\n    def get(self, request, *args, **kwargs):\n        return self.http_method_not_allowed(request, *args, **kwargs)\n\n    def form_invalid(self, form):\n        return HttpResponse('Invalid group selection')\n\n    def form_valid(self, form):\n        enrollment = form.save()\n        if self.request.is_ajax():\n            return self.render_to_response(self.get_context_data(\n                **group_info_context(enrollment.selected_group, self.profile)))\n        return super().form_valid(form)\n", "path": "course/views.py"}], "after_files": [{"content": "import datetime\n\nimport icalendar\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404\nfrom django.http.response import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import html\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom authorization.permissions import ACCESS\nfrom exercise.cache.hierarchy import NoSuchContent\nfrom exercise.models import LearningObject\nfrom lib.helpers import settings_text\nfrom lib.viewbase import BaseTemplateView, BaseRedirectMixin, BaseFormView, BaseView\nfrom userprofile.viewbase import UserProfileView\nfrom .forms import GroupsForm, GroupSelectForm\nfrom .models import CourseInstance, Enrollment\nfrom .permissions import EnrollInfoVisiblePermission\nfrom .renders import group_info_context\nfrom .viewbase import CourseModuleBaseView, CourseInstanceMixin, EnrollableViewMixin\n\n\nclass HomeView(UserProfileView):\n    access_mode = ACCESS.ANONYMOUS\n    template_name = \"course/index.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.welcome_text = settings_text('WELCOME_TEXT')\n        self.internal_user_label = settings_text('INTERNAL_USER_LABEL')\n        self.external_user_label = settings_text('EXTERNAL_USER_LABEL')\n        my_instances = []\n        all_instances = []\n        end_threshold = timezone.now() - datetime.timedelta(days=30)\n        user = self.request.user\n        is_logged_in = False\n\n        if user and user.is_authenticated:\n            is_logged_in = True\n            for instance in (CourseInstance.objects\n                .filter(course__teachers=user.userprofile,\n                        ending_time__gte=end_threshold)\n                .all()):\n                my_instances.append(instance)\n\n            for instance in user.userprofile.assisting_courses.all().filter(ending_time__gte=end_threshold):\n                if instance not in my_instances:\n                    my_instances.append(instance)\n            \n            for instance in user.userprofile.enrolled.all().filter(ending_time__gte=end_threshold):\n                if instance not in my_instances:\n                    my_instances.append(instance)\n        \n        all_instances = CourseInstance.objects.get_visible(user).filter(ending_time__gte=end_threshold)\n        all_instances = [c for c in all_instances if c not in my_instances]\n        \n        self.all_instances = all_instances\n        self.my_instances = my_instances\n        self.is_logged_in = is_logged_in\n\n        self.note(\"welcome_text\", \n            \"internal_user_label\", \n            \"external_user_label\",\n            \"my_instances\",\n            \"all_instances\",\n            \"is_logged_in\",\n        )\n\n\nclass ArchiveView(UserProfileView):\n    access_mode = ACCESS.ANONYMOUS\n    template_name = \"course/archive.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.instances = CourseInstance.objects.get_visible(self.request.user)\n        self.note(\"instances\")\n\nclass InstanceView(EnrollableViewMixin, BaseTemplateView):\n    access_mode = ACCESS.STUDENT\n    # ACCESS.STUDENT requires users to log in, but the access mode is dropped\n    # in public courses. CourseVisiblePermission has more restrictions as well.\n    template_name = \"course/course.html\"\n\n    def handle_no_permission(self):\n        if self.request.user.is_authenticated \\\n                and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED:\n            # The course instance is visible to only enrolled students, so\n            # redirect the user to the enroll page instead of showing\n            # a 403 Forbidden error.\n            return redirect(self.instance.get_url('enroll'))\n        return super().handle_no_permission()\n\n    def get(self, request, *args, **kwargs):\n        # external LTI Tool Providers may return the user to the course instance view\n        # with a message given in GET query parameters\n        lti_error_msg = request.GET.get('lti_errormsg')\n        lti_msg = request.GET.get('lti_msg')\n        # message HTML is not escaped in the templates so escape it here\n        if lti_error_msg:\n            messages.error(request, html.escape(lti_error_msg))\n        elif lti_msg:\n            messages.info(request, html.escape(lti_msg))\n\n        later_instance = None\n\n        if self.instance.is_past:\n            try:\n                later_instance = (\n                    CourseInstance.objects\n                        .get_visible(request.user)\n                        .filter(course=self.course, ending_time__gte=timezone.now())\n                        .latest('starting_time')\n                )\n            except CourseInstance.DoesNotExist:\n                pass\n\n        kwargs['later_instance'] = later_instance\n\n        return super().get(request, *args, **kwargs)\n\nclass Enroll(EnrollableViewMixin, BaseRedirectMixin, BaseTemplateView):\n    permission_classes = [EnrollInfoVisiblePermission]\n    course_permission_classes = []\n    template_name = \"course/enroll.html\"\n\n    def post(self, request, *args, **kwargs):\n\n        if self.is_student or not self.enrollable:\n            messages.error(self.request, _(\"You cannot enroll, or have already enrolled, in this course.\"))\n            raise PermissionDenied()\n\n        if not self.instance.is_enrollment_open():\n            messages.error(self.request, _(\"The enrollment is not open.\"))\n            raise PermissionDenied()\n\n        # Support enrollment questionnaires.\n        exercise = LearningObject.objects.find_enrollment_exercise(\n            self.instance, self.profile)\n        if exercise:\n            return self.redirect(exercise.get_absolute_url())\n\n        self.instance.enroll_student(self.request.user)\n        return self.redirect(self.instance.get_absolute_url())\n\n\nclass ModuleView(CourseModuleBaseView):\n    template_name = \"course/module.html\"\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.now = timezone.now()\n        try:\n            self.children = self.content.flat_module(self.module)\n            cur, tree, prev, nex = self.content.find(self.module)\n            self.previous = prev\n            self.current = cur\n            self.next = nex\n        except NoSuchContent:\n            raise Http404\n        self.note('now', 'children', 'previous', 'current', 'next')\n\n\nclass CalendarExport(CourseInstanceMixin, BaseView):\n\n    def get(self, request, *args, **kwargs):\n        cal = icalendar.Calendar()\n        cal.add('prodid', '-// {} calendar //'.format(settings.BRAND_NAME))\n        cal.add('version', '2.0')\n        for module in self.instance.course_modules.all():\n            event = icalendar.Event()\n            event.add('summary', module.name)\n            event.add('dtstart',\n                module.closing_time - datetime.timedelta(hours=1))\n            event.add('dtend', module.closing_time)\n            event.add('dtstamp', module.closing_time)\n            event['uid'] = \"module/\" + str(module.id) + \"/A+\"\n            cal.add_component(event)\n\n        return HttpResponse(cal.to_ical(),\n            content_type=\"text/calendar; charset=utf-8\")\n\n\nclass GroupsView(CourseInstanceMixin, BaseFormView):\n    access_mode = ACCESS.ENROLLED\n    template_name = \"course/groups.html\"\n    form_class = GroupsForm\n\n    def get_common_objects(self):\n        super().get_common_objects()\n        self.enrollment = self.instance.get_enrollment_for(self.request.user)\n        self.groups = list(self.profile.groups.filter(course_instance=self.instance))\n        self.note('enrollment','groups')\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"profile\"] = self.profile\n        kwargs[\"instance\"] = self.instance\n        kwargs[\"content\"] = self.content\n        return kwargs\n\n    def get_success_url(self):\n        return self.instance.get_url('groups')\n\n    def form_valid(self, form):\n        form.save()\n        messages.success(self.request, _(\"A new student group was created.\"))\n        return super().form_valid(form)\n\n\nclass GroupSelect(CourseInstanceMixin, BaseFormView):\n    access_mode = ACCESS.ENROLLED\n    form_class = GroupSelectForm\n    template_name = \"course/_group_info.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"profile\"] = self.profile\n        kwargs[\"instance\"] = self.instance\n        return kwargs\n\n    def get_success_url(self):\n        return self.instance.get_absolute_url()\n\n    def get(self, request, *args, **kwargs):\n        return self.http_method_not_allowed(request, *args, **kwargs)\n\n    def form_invalid(self, form):\n        return HttpResponse('Invalid group selection')\n\n    def form_valid(self, form):\n        enrollment = form.save()\n        if self.request.is_ajax():\n            return self.render_to_response(self.get_context_data(\n                **group_info_context(enrollment.selected_group, self.profile)))\n        return super().form_valid(form)\n", "path": "course/views.py"}]}