We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Problems with Enrollment questionnaire and SISU enrollments
Quite recently a new "PENDING" enrollment state was added to support enrollment questionnaires with courses where students are enrolled from SISU. On summer Y1 course this feature was first time in use in production, but does not appear to work properly. Students are set to PENDING state properly when fetched from SISU, but are not redirected to enrollment questionnaire properly as they should. Instead they get "You must enrol on this course through Student Information System." note which should not be shown in this case.

--- 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/viewbase.py`
Content:
```
1 from django.contrib import messages
2 from django.core.exceptions import PermissionDenied
3 from django.http import Http404
4 from django.shortcuts import get_object_or_404, redirect, render
5 from django.utils import translation
6 from django.utils.translation import gettext_lazy as _
7 from django.utils.translation import get_language, get_language_info
8 
9 from authorization.permissions import ACCESS
10 from exercise.cache.content import CachedContent
11 from lib.helpers import remove_query_param_from_url, update_url_params
12 from lib.viewbase import BaseTemplateView
13 from userprofile.viewbase import UserProfileMixin
14 from .cache.students import CachedStudent
15 from .exceptions import TranslationNotFound
16 from .permissions import (
17     CourseVisiblePermission,
18     CourseModulePermission,
19 )
20 from .models import Course, CourseInstance, CourseModule, UserTagging
21 
22 
23 class CourseMixin(UserProfileMixin):
24     course_kw = "course_slug"
25 
26     def get_resource_objects(self):
27         super().get_resource_objects()
28         self.course = get_object_or_404(
29             Course,
30             url=self._get_kwarg(self.course_kw)
31         )
32         self.note("course")
33 
34 
35 class CourseBaseView(CourseMixin, BaseTemplateView):
36     pass
37 
38 
39 class CourseInstanceBaseMixin(object):
40     course_kw = CourseMixin.course_kw
41     instance_kw = "instance_slug"
42     course_permission_classes = (
43         CourseVisiblePermission,
44     )
45 
46     def get_permissions(self):
47         perms = super().get_permissions()
48         perms.extend((Perm() for Perm in self.course_permission_classes))
49         return perms
50 
51     # get_course_instance_object
52 
53     def get_resource_objects(self):
54         super().get_resource_objects()
55         user = self.request.user
56         instance = self.get_course_instance_object()
57         if instance is not None:
58             self.instance = instance
59             self.course = self.instance.course
60             self.content = CachedContent(self.instance)
61             self.user_course_data = None
62             is_real_user = user.is_authenticated and not user.is_anonymous
63             if is_real_user:
64                 self.user_course_data = self.instance.get_enrollment_for(user)
65             self.is_student = self.instance.is_student(user)
66             self.is_assistant = self.instance.is_assistant(user)
67             self.is_teacher = self.instance.is_teacher(user)
68             self.is_course_staff = self.is_teacher or self.is_assistant
69             self.get_taggings = lambda: CachedStudent(instance, user.id).data['tag_slugs']
70             self.url_without_language = remove_query_param_from_url(self.request.get_full_path(), 'hl')
71             self.query_language = None
72             self.user_language = None
73 
74             self.note(
75                 "course", "instance", "content", "user_course_data", "is_student", "is_assistant",
76                 "is_teacher", "is_course_staff", "get_taggings", "url_without_language",
77                 "query_language", "user_language"
78             )
79 
80             # Try to find a language that is defined for this course instance
81             # and apply it
82             if self.instance.language:
83                 instance_languages = self.instance.language.strip('|').split('|')
84                 instance_def_language = instance_languages[0]
85                 instance_languages = set(instance_languages)
86 
87                 languages = []
88                 if self.user_course_data and self.user_course_data.language:
89                     languages.append(self.user_course_data.language)
90                 if is_real_user and user.userprofile.language:
91                     languages.append(user.userprofile.language)
92                 languages.append(get_language())
93 
94                 query_language = self.request.GET.get('hl')
95                 if query_language:
96                     if query_language[:2] in instance_languages:
97                         language = query_language
98                         if languages:
99                             self.user_language = languages[0]
100                             if self.user_language[:2] != query_language[:2]:
101                                 self.query_language = query_language
102                     else:
103                         raise TranslationNotFound
104                 else:
105                     for lang in languages:
106                         if lang[:2] in instance_languages:
107                             language = lang
108                             break
109                     else:
110                         language = instance_def_language
111 
112                 language = language[:2]
113                 # Override request.LANGUAGE_CODE. It is set in lib/middleware.py
114                 # (class LocaleMiddleware) based on the userprofile.language.
115                 # The middleware can not easily access the course context and
116                 # the language from the enrollment. That is fixed here.
117                 self.request.LANGUAGE_CODE = language
118                 translation.activate(language)
119 
120     def get_access_mode(self):
121         access_mode = super().get_access_mode()
122 
123         if hasattr(self, 'instance'):
124             # Loosen the access mode if instance is public
125             show_for = self.instance.view_content_to
126             is_public = show_for == CourseInstance.VIEW_ACCESS.PUBLIC
127             access_mode_student = access_mode in (ACCESS.STUDENT, ACCESS.ENROLL)
128             if is_public and access_mode_student:
129                 access_mode = ACCESS.ANONYMOUS
130 
131         return access_mode
132 
133     def handle_exception(self, exc):
134         if isinstance(exc, TranslationNotFound):
135             instance_languages = self.instance.language.strip("|").split("|")
136             url = remove_query_param_from_url(self.request.get_full_path(), 'hl')
137             for i, lang in enumerate(instance_languages):
138                 instance_languages[i] = {"name": get_language_info(lang)['name'], "url": update_url_params(url, {'hl' : lang})}
139             return render(self.request, '404.html', {'error_msg': str(exc), 'languages': instance_languages}, status=404)
140         return super().handle_exception(exc)
141 
142 class CourseInstanceMixin(CourseInstanceBaseMixin, UserProfileMixin):
143     def get_course_instance_object(self) -> CourseInstance:
144         return get_object_or_404(
145             CourseInstance.objects.prefetch_related('tabs'),
146             url=self.kwargs[self.instance_kw],
147             course__url=self.kwargs[self.course_kw],
148         )
149 
150     def handle_no_permission(self):
151         if (self.request.user.is_authenticated
152                 and not self.is_student
153                 and not self.is_course_staff
154                 and self.get_access_mode() in [ACCESS.STUDENT, ACCESS.ENROLLED]
155                 and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED):
156             # Redirect the user to the enrollment page instead of showing
157             # a 403 Forbidden error, if:
158             # - the user is signed in but not enrolled or staff
159             # - the page is not a teacher page (e.g. edit course)
160             # - the course is visible only to enrolled students
161             return redirect(self.instance.get_url('enroll'))
162         return super().handle_no_permission()
163 
164 
165 class CourseInstanceBaseView(CourseInstanceMixin, BaseTemplateView):
166     pass
167 
168 
169 class EnrollableViewMixin(CourseInstanceMixin):
170     access_mode = ACCESS.ENROLL
171 
172     def get_common_objects(self):
173         self.enrolled = self.is_student
174         self.enrollable = (
175             self.profile
176             and self.instance.is_enrollable(self.profile.user)
177         )
178         self.note('enrolled', 'enrollable')
179 
180 
181 class CourseModuleBaseMixin(object):
182     module_kw = "module_slug"
183     module_permissions_classes = (
184         CourseModulePermission,
185     )
186 
187     def get_permissions(self):
188         perms = super().get_permissions()
189         perms.extend((Perm() for Perm in self.module_permissions_classes))
190         return perms
191 
192     # get_course_module_object
193 
194     def get_resource_objects(self):
195         super().get_resource_objects()
196         self.module = self.get_course_module_object()
197         self.note("module")
198 
199 
200 class CourseModuleMixin(CourseModuleBaseMixin, CourseInstanceMixin):
201     def get_course_module_object(self):
202         return get_object_or_404(
203             CourseModule,
204             url=self.kwargs[self.module_kw],
205             course_instance=self.instance
206         )
207 
208 
209 class CourseModuleBaseView(CourseModuleMixin, BaseTemplateView):
210     pass
211
```
--- 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/viewbase.py b/course/viewbase.py
--- a/course/viewbase.py
+++ b/course/viewbase.py
@@ -11,13 +11,14 @@
 from lib.helpers import remove_query_param_from_url, update_url_params
 from lib.viewbase import BaseTemplateView
 from userprofile.viewbase import UserProfileMixin
+from exercise.models import LearningObject
 from .cache.students import CachedStudent
 from .exceptions import TranslationNotFound
 from .permissions import (
     CourseVisiblePermission,
     CourseModulePermission,
 )
-from .models import Course, CourseInstance, CourseModule, UserTagging
+from .models import Course, CourseInstance, CourseModule, UserTagging, Enrollment
 
 
 class CourseMixin(UserProfileMixin):
@@ -158,6 +159,15 @@
             # - the user is signed in but not enrolled or staff
             # - the page is not a teacher page (e.g. edit course)
             # - the course is visible only to enrolled students
+            #
+            # If SIS enrollment is applied and course requires enrollment questionnaire,
+            # redirect to the questionnaire instead.
+            enrollment = self.user_course_data
+            if enrollment and enrollment.status == Enrollment.ENROLLMENT_STATUS.PENDING:
+                exercise = LearningObject.objects.find_enrollment_exercise(
+                    self.instance, self.profile.is_external)
+                if exercise:
+                    return self.redirect(exercise.get_absolute_url())
             return redirect(self.instance.get_url('enroll'))
         return super().handle_no_permission()

{"golden_diff": "diff --git a/course/viewbase.py b/course/viewbase.py\n--- a/course/viewbase.py\n+++ b/course/viewbase.py\n@@ -11,13 +11,14 @@\n from lib.helpers import remove_query_param_from_url, update_url_params\n from lib.viewbase import BaseTemplateView\n from userprofile.viewbase import UserProfileMixin\n+from exercise.models import LearningObject\n from .cache.students import CachedStudent\n from .exceptions import TranslationNotFound\n from .permissions import (\n     CourseVisiblePermission,\n     CourseModulePermission,\n )\n-from .models import Course, CourseInstance, CourseModule, UserTagging\n+from .models import Course, CourseInstance, CourseModule, UserTagging, Enrollment\n \n \n class CourseMixin(UserProfileMixin):\n@@ -158,6 +159,15 @@\n             # - the user is signed in but not enrolled or staff\n             # - the page is not a teacher page (e.g. edit course)\n             # - the course is visible only to enrolled students\n+            #\n+            # If SIS enrollment is applied and course requires enrollment questionnaire,\n+            # redirect to the questionnaire instead.\n+            enrollment = self.user_course_data\n+            if enrollment and enrollment.status == Enrollment.ENROLLMENT_STATUS.PENDING:\n+                exercise = LearningObject.objects.find_enrollment_exercise(\n+                    self.instance, self.profile.is_external)\n+                if exercise:\n+                    return self.redirect(exercise.get_absolute_url())\n             return redirect(self.instance.get_url('enroll'))\n         return super().handle_no_permission()\n", "issue": "Problems with Enrollment questionnaire and SISU enrollments\nQuite recently a new \"PENDING\" enrollment state was added to support enrollment questionnaires with courses where students are enrolled from SISU. On summer Y1 course this feature was first time in use in production, but does not appear to work properly. Students are set to PENDING state properly when fetched from SISU, but are not redirected to enrollment questionnaire properly as they should. Instead they get \"You must enrol on this course through Student Information System.\" note which should not be shown in this case.\n", "before_files": [{"content": "from django.contrib import messages\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils import translation\nfrom django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import get_language, get_language_info\n\nfrom authorization.permissions import ACCESS\nfrom exercise.cache.content import CachedContent\nfrom lib.helpers import remove_query_param_from_url, update_url_params\nfrom lib.viewbase import BaseTemplateView\nfrom userprofile.viewbase import UserProfileMixin\nfrom .cache.students import CachedStudent\nfrom .exceptions import TranslationNotFound\nfrom .permissions import (\n    CourseVisiblePermission,\n    CourseModulePermission,\n)\nfrom .models import Course, CourseInstance, CourseModule, UserTagging\n\n\nclass CourseMixin(UserProfileMixin):\n    course_kw = \"course_slug\"\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        self.course = get_object_or_404(\n            Course,\n            url=self._get_kwarg(self.course_kw)\n        )\n        self.note(\"course\")\n\n\nclass CourseBaseView(CourseMixin, BaseTemplateView):\n    pass\n\n\nclass CourseInstanceBaseMixin(object):\n    course_kw = CourseMixin.course_kw\n    instance_kw = \"instance_slug\"\n    course_permission_classes = (\n        CourseVisiblePermission,\n    )\n\n    def get_permissions(self):\n        perms = super().get_permissions()\n        perms.extend((Perm() for Perm in self.course_permission_classes))\n        return perms\n\n    # get_course_instance_object\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        user = self.request.user\n        instance = self.get_course_instance_object()\n        if instance is not None:\n            self.instance = instance\n            self.course = self.instance.course\n            self.content = CachedContent(self.instance)\n            self.user_course_data = None\n            is_real_user = user.is_authenticated and not user.is_anonymous\n            if is_real_user:\n                self.user_course_data = self.instance.get_enrollment_for(user)\n            self.is_student = self.instance.is_student(user)\n            self.is_assistant = self.instance.is_assistant(user)\n            self.is_teacher = self.instance.is_teacher(user)\n            self.is_course_staff = self.is_teacher or self.is_assistant\n            self.get_taggings = lambda: CachedStudent(instance, user.id).data['tag_slugs']\n            self.url_without_language = remove_query_param_from_url(self.request.get_full_path(), 'hl')\n            self.query_language = None\n            self.user_language = None\n\n            self.note(\n                \"course\", \"instance\", \"content\", \"user_course_data\", \"is_student\", \"is_assistant\",\n                \"is_teacher\", \"is_course_staff\", \"get_taggings\", \"url_without_language\",\n                \"query_language\", \"user_language\"\n            )\n\n            # Try to find a language that is defined for this course instance\n            # and apply it\n            if self.instance.language:\n                instance_languages = self.instance.language.strip('|').split('|')\n                instance_def_language = instance_languages[0]\n                instance_languages = set(instance_languages)\n\n                languages = []\n                if self.user_course_data and self.user_course_data.language:\n                    languages.append(self.user_course_data.language)\n                if is_real_user and user.userprofile.language:\n                    languages.append(user.userprofile.language)\n                languages.append(get_language())\n\n                query_language = self.request.GET.get('hl')\n                if query_language:\n                    if query_language[:2] in instance_languages:\n                        language = query_language\n                        if languages:\n                            self.user_language = languages[0]\n                            if self.user_language[:2] != query_language[:2]:\n                                self.query_language = query_language\n                    else:\n                        raise TranslationNotFound\n                else:\n                    for lang in languages:\n                        if lang[:2] in instance_languages:\n                            language = lang\n                            break\n                    else:\n                        language = instance_def_language\n\n                language = language[:2]\n                # Override request.LANGUAGE_CODE. It is set in lib/middleware.py\n                # (class LocaleMiddleware) based on the userprofile.language.\n                # The middleware can not easily access the course context and\n                # the language from the enrollment. That is fixed here.\n                self.request.LANGUAGE_CODE = language\n                translation.activate(language)\n\n    def get_access_mode(self):\n        access_mode = super().get_access_mode()\n\n        if hasattr(self, 'instance'):\n            # Loosen the access mode if instance is public\n            show_for = self.instance.view_content_to\n            is_public = show_for == CourseInstance.VIEW_ACCESS.PUBLIC\n            access_mode_student = access_mode in (ACCESS.STUDENT, ACCESS.ENROLL)\n            if is_public and access_mode_student:\n                access_mode = ACCESS.ANONYMOUS\n\n        return access_mode\n\n    def handle_exception(self, exc):\n        if isinstance(exc, TranslationNotFound):\n            instance_languages = self.instance.language.strip(\"|\").split(\"|\")\n            url = remove_query_param_from_url(self.request.get_full_path(), 'hl')\n            for i, lang in enumerate(instance_languages):\n                instance_languages[i] = {\"name\": get_language_info(lang)['name'], \"url\": update_url_params(url, {'hl' : lang})}\n            return render(self.request, '404.html', {'error_msg': str(exc), 'languages': instance_languages}, status=404)\n        return super().handle_exception(exc)\n\nclass CourseInstanceMixin(CourseInstanceBaseMixin, UserProfileMixin):\n    def get_course_instance_object(self) -> CourseInstance:\n        return get_object_or_404(\n            CourseInstance.objects.prefetch_related('tabs'),\n            url=self.kwargs[self.instance_kw],\n            course__url=self.kwargs[self.course_kw],\n        )\n\n    def handle_no_permission(self):\n        if (self.request.user.is_authenticated\n                and not self.is_student\n                and not self.is_course_staff\n                and self.get_access_mode() in [ACCESS.STUDENT, ACCESS.ENROLLED]\n                and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED):\n            # Redirect the user to the enrollment page instead of showing\n            # a 403 Forbidden error, if:\n            # - the user is signed in but not enrolled or staff\n            # - the page is not a teacher page (e.g. edit course)\n            # - the course is visible only to enrolled students\n            return redirect(self.instance.get_url('enroll'))\n        return super().handle_no_permission()\n\n\nclass CourseInstanceBaseView(CourseInstanceMixin, BaseTemplateView):\n    pass\n\n\nclass EnrollableViewMixin(CourseInstanceMixin):\n    access_mode = ACCESS.ENROLL\n\n    def get_common_objects(self):\n        self.enrolled = self.is_student\n        self.enrollable = (\n            self.profile\n            and self.instance.is_enrollable(self.profile.user)\n        )\n        self.note('enrolled', 'enrollable')\n\n\nclass CourseModuleBaseMixin(object):\n    module_kw = \"module_slug\"\n    module_permissions_classes = (\n        CourseModulePermission,\n    )\n\n    def get_permissions(self):\n        perms = super().get_permissions()\n        perms.extend((Perm() for Perm in self.module_permissions_classes))\n        return perms\n\n    # get_course_module_object\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        self.module = self.get_course_module_object()\n        self.note(\"module\")\n\n\nclass CourseModuleMixin(CourseModuleBaseMixin, CourseInstanceMixin):\n    def get_course_module_object(self):\n        return get_object_or_404(\n            CourseModule,\n            url=self.kwargs[self.module_kw],\n            course_instance=self.instance\n        )\n\n\nclass CourseModuleBaseView(CourseModuleMixin, BaseTemplateView):\n    pass\n", "path": "course/viewbase.py"}], "after_files": [{"content": "from django.contrib import messages\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils import translation\nfrom django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import get_language, get_language_info\n\nfrom authorization.permissions import ACCESS\nfrom exercise.cache.content import CachedContent\nfrom lib.helpers import remove_query_param_from_url, update_url_params\nfrom lib.viewbase import BaseTemplateView\nfrom userprofile.viewbase import UserProfileMixin\nfrom exercise.models import LearningObject\nfrom .cache.students import CachedStudent\nfrom .exceptions import TranslationNotFound\nfrom .permissions import (\n    CourseVisiblePermission,\n    CourseModulePermission,\n)\nfrom .models import Course, CourseInstance, CourseModule, UserTagging, Enrollment\n\n\nclass CourseMixin(UserProfileMixin):\n    course_kw = \"course_slug\"\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        self.course = get_object_or_404(\n            Course,\n            url=self._get_kwarg(self.course_kw)\n        )\n        self.note(\"course\")\n\n\nclass CourseBaseView(CourseMixin, BaseTemplateView):\n    pass\n\n\nclass CourseInstanceBaseMixin(object):\n    course_kw = CourseMixin.course_kw\n    instance_kw = \"instance_slug\"\n    course_permission_classes = (\n        CourseVisiblePermission,\n    )\n\n    def get_permissions(self):\n        perms = super().get_permissions()\n        perms.extend((Perm() for Perm in self.course_permission_classes))\n        return perms\n\n    # get_course_instance_object\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        user = self.request.user\n        instance = self.get_course_instance_object()\n        if instance is not None:\n            self.instance = instance\n            self.course = self.instance.course\n            self.content = CachedContent(self.instance)\n            self.user_course_data = None\n            is_real_user = user.is_authenticated and not user.is_anonymous\n            if is_real_user:\n                self.user_course_data = self.instance.get_enrollment_for(user)\n            self.is_student = self.instance.is_student(user)\n            self.is_assistant = self.instance.is_assistant(user)\n            self.is_teacher = self.instance.is_teacher(user)\n            self.is_course_staff = self.is_teacher or self.is_assistant\n            self.get_taggings = lambda: CachedStudent(instance, user.id).data['tag_slugs']\n            self.url_without_language = remove_query_param_from_url(self.request.get_full_path(), 'hl')\n            self.query_language = None\n            self.user_language = None\n\n            self.note(\n                \"course\", \"instance\", \"content\", \"user_course_data\", \"is_student\", \"is_assistant\",\n                \"is_teacher\", \"is_course_staff\", \"get_taggings\", \"url_without_language\",\n                \"query_language\", \"user_language\"\n            )\n\n            # Try to find a language that is defined for this course instance\n            # and apply it\n            if self.instance.language:\n                instance_languages = self.instance.language.strip('|').split('|')\n                instance_def_language = instance_languages[0]\n                instance_languages = set(instance_languages)\n\n                languages = []\n                if self.user_course_data and self.user_course_data.language:\n                    languages.append(self.user_course_data.language)\n                if is_real_user and user.userprofile.language:\n                    languages.append(user.userprofile.language)\n                languages.append(get_language())\n\n                query_language = self.request.GET.get('hl')\n                if query_language:\n                    if query_language[:2] in instance_languages:\n                        language = query_language\n                        if languages:\n                            self.user_language = languages[0]\n                            if self.user_language[:2] != query_language[:2]:\n                                self.query_language = query_language\n                    else:\n                        raise TranslationNotFound\n                else:\n                    for lang in languages:\n                        if lang[:2] in instance_languages:\n                            language = lang\n                            break\n                    else:\n                        language = instance_def_language\n\n                language = language[:2]\n                # Override request.LANGUAGE_CODE. It is set in lib/middleware.py\n                # (class LocaleMiddleware) based on the userprofile.language.\n                # The middleware can not easily access the course context and\n                # the language from the enrollment. That is fixed here.\n                self.request.LANGUAGE_CODE = language\n                translation.activate(language)\n\n    def get_access_mode(self):\n        access_mode = super().get_access_mode()\n\n        if hasattr(self, 'instance'):\n            # Loosen the access mode if instance is public\n            show_for = self.instance.view_content_to\n            is_public = show_for == CourseInstance.VIEW_ACCESS.PUBLIC\n            access_mode_student = access_mode in (ACCESS.STUDENT, ACCESS.ENROLL)\n            if is_public and access_mode_student:\n                access_mode = ACCESS.ANONYMOUS\n\n        return access_mode\n\n    def handle_exception(self, exc):\n        if isinstance(exc, TranslationNotFound):\n            instance_languages = self.instance.language.strip(\"|\").split(\"|\")\n            url = remove_query_param_from_url(self.request.get_full_path(), 'hl')\n            for i, lang in enumerate(instance_languages):\n                instance_languages[i] = {\"name\": get_language_info(lang)['name'], \"url\": update_url_params(url, {'hl' : lang})}\n            return render(self.request, '404.html', {'error_msg': str(exc), 'languages': instance_languages}, status=404)\n        return super().handle_exception(exc)\n\nclass CourseInstanceMixin(CourseInstanceBaseMixin, UserProfileMixin):\n    def get_course_instance_object(self) -> CourseInstance:\n        return get_object_or_404(\n            CourseInstance.objects.prefetch_related('tabs'),\n            url=self.kwargs[self.instance_kw],\n            course__url=self.kwargs[self.course_kw],\n        )\n\n    def handle_no_permission(self):\n        if (self.request.user.is_authenticated\n                and not self.is_student\n                and not self.is_course_staff\n                and self.get_access_mode() in [ACCESS.STUDENT, ACCESS.ENROLLED]\n                and self.instance.view_content_to == CourseInstance.VIEW_ACCESS.ENROLLED):\n            # Redirect the user to the enrollment page instead of showing\n            # a 403 Forbidden error, if:\n            # - the user is signed in but not enrolled or staff\n            # - the page is not a teacher page (e.g. edit course)\n            # - the course is visible only to enrolled students\n            #\n            # If SIS enrollment is applied and course requires enrollment questionnaire,\n            # redirect to the questionnaire instead.\n            enrollment = self.user_course_data\n            if enrollment and enrollment.status == Enrollment.ENROLLMENT_STATUS.PENDING:\n                exercise = LearningObject.objects.find_enrollment_exercise(\n                    self.instance, self.profile.is_external)\n                if exercise:\n                    return self.redirect(exercise.get_absolute_url())\n            return redirect(self.instance.get_url('enroll'))\n        return super().handle_no_permission()\n\n\nclass CourseInstanceBaseView(CourseInstanceMixin, BaseTemplateView):\n    pass\n\n\nclass EnrollableViewMixin(CourseInstanceMixin):\n    access_mode = ACCESS.ENROLL\n\n    def get_common_objects(self):\n        self.enrolled = self.is_student\n        self.enrollable = (\n            self.profile\n            and self.instance.is_enrollable(self.profile.user)\n        )\n        self.note('enrolled', 'enrollable')\n\n\nclass CourseModuleBaseMixin(object):\n    module_kw = \"module_slug\"\n    module_permissions_classes = (\n        CourseModulePermission,\n    )\n\n    def get_permissions(self):\n        perms = super().get_permissions()\n        perms.extend((Perm() for Perm in self.module_permissions_classes))\n        return perms\n\n    # get_course_module_object\n\n    def get_resource_objects(self):\n        super().get_resource_objects()\n        self.module = self.get_course_module_object()\n        self.note(\"module\")\n\n\nclass CourseModuleMixin(CourseModuleBaseMixin, CourseInstanceMixin):\n    def get_course_module_object(self):\n        return get_object_or_404(\n            CourseModule,\n            url=self.kwargs[self.module_kw],\n            course_instance=self.instance\n        )\n\n\nclass CourseModuleBaseView(CourseModuleMixin, BaseTemplateView):\n    pass\n", "path": "course/viewbase.py"}]}