|
3 | 3 | from django.conf import settings
|
4 | 4 | from django.shortcuts import get_object_or_404
|
5 | 5 | from django.template import loader as template_loader
|
6 |
| -from rest_framework import decorators, permissions |
| 6 | +from rest_framework.permissions import AllowAny |
7 | 7 | from rest_framework.renderers import JSONRenderer
|
8 | 8 | from rest_framework.response import Response
|
| 9 | +from rest_framework.views import APIView |
9 | 10 | from rest_framework_jsonp.renderers import JSONPRenderer
|
10 | 11 |
|
11 | 12 | from readthedocs.api.v2.signals import footer_response
|
@@ -63,113 +64,156 @@ def get_version_compare_data(project, base_version=None):
|
63 | 64 | return ret_val
|
64 | 65 |
|
65 | 66 |
|
66 |
| -@decorators.api_view(['GET']) |
67 |
| -@decorators.permission_classes((permissions.AllowAny,)) |
68 |
| -@decorators.renderer_classes((JSONRenderer, JSONPRenderer)) |
69 |
| -def footer_html(request): |
70 |
| - """Render and return footer markup.""" |
71 |
| - # TODO refactor this function |
72 |
| - # pylint: disable=too-many-locals |
73 |
| - project_slug = request.GET.get('project', None) |
74 |
| - version_slug = request.GET.get('version', None) |
75 |
| - page_slug = request.GET.get('page', '') |
76 |
| - theme = request.GET.get('theme', False) |
77 |
| - docroot = request.GET.get('docroot', '') |
78 |
| - subproject = request.GET.get('subproject', False) |
79 |
| - source_suffix = request.GET.get('source_suffix', '.rst') |
80 |
| - |
81 |
| - # Hack in a fix for missing version slug deploy that went out a while back |
82 |
| - if version_slug == '': |
83 |
| - version_slug = LATEST |
84 |
| - |
85 |
| - new_theme = (theme == 'sphinx_rtd_theme') |
86 |
| - using_theme = (theme == 'default') |
87 |
| - project = get_object_or_404(Project, slug=project_slug) |
88 |
| - version = get_object_or_404( |
89 |
| - Version.objects.public( |
90 |
| - request.user, |
91 |
| - project=project, |
92 |
| - only_active=False, |
93 |
| - ), |
94 |
| - slug__iexact=version_slug, |
95 |
| - ) |
96 |
| - main_project = project.main_language_project or project |
| 67 | +class FooterHTML(APIView): |
97 | 68 |
|
98 |
| - if page_slug and page_slug != 'index': |
99 |
| - if main_project.documentation_type == 'sphinx_htmldir': |
100 |
| - path = page_slug + '/' |
101 |
| - else: |
102 |
| - path = page_slug + '.html' |
103 |
| - else: |
104 |
| - path = '' |
105 |
| - |
106 |
| - version_compare_data = get_version_compare_data(project, version) |
107 |
| - |
108 |
| - context = { |
109 |
| - 'project': project, |
110 |
| - 'version': version, |
111 |
| - 'path': path, |
112 |
| - 'downloads': version.get_downloads(pretty=True), |
113 |
| - 'current_version': version.verbose_name, |
114 |
| - 'versions': project.ordered_active_versions(user=request.user), |
115 |
| - 'main_project': main_project, |
116 |
| - 'translations': main_project.translations.all(), |
117 |
| - 'current_language': project.language, |
118 |
| - 'using_theme': using_theme, |
119 |
| - 'new_theme': new_theme, |
120 |
| - 'settings': settings, |
121 |
| - 'subproject': subproject, |
122 |
| - 'github_edit_url': version.get_github_url( |
123 |
| - docroot, |
124 |
| - page_slug, |
125 |
| - source_suffix, |
126 |
| - 'edit', |
127 |
| - ), |
128 |
| - 'github_view_url': version.get_github_url( |
129 |
| - docroot, |
130 |
| - page_slug, |
131 |
| - source_suffix, |
132 |
| - 'view', |
133 |
| - ), |
134 |
| - 'gitlab_edit_url': version.get_gitlab_url( |
135 |
| - docroot, |
136 |
| - page_slug, |
137 |
| - source_suffix, |
138 |
| - 'edit', |
139 |
| - ), |
140 |
| - 'gitlab_view_url': version.get_gitlab_url( |
141 |
| - docroot, |
142 |
| - page_slug, |
143 |
| - source_suffix, |
144 |
| - 'view', |
145 |
| - ), |
146 |
| - 'bitbucket_url': version.get_bitbucket_url( |
147 |
| - docroot, |
148 |
| - page_slug, |
149 |
| - source_suffix, |
150 |
| - ), |
151 |
| - 'theme': theme, |
152 |
| - } |
| 69 | + """ |
| 70 | + Render and return footer markup. |
153 | 71 |
|
154 |
| - html = template_loader.get_template('restapi/footer.html').render( |
155 |
| - context, |
156 |
| - request, |
157 |
| - ) |
158 |
| - resp_data = { |
159 |
| - 'html': html, |
160 |
| - 'show_version_warning': project.show_version_warning, |
161 |
| - 'version_active': version.active, |
162 |
| - 'version_compare': version_compare_data, |
163 |
| - 'version_supported': version.supported, |
164 |
| - } |
| 72 | + .. note:: |
165 | 73 |
|
166 |
| - # Allow folks to hook onto the footer response for various information |
167 |
| - # collection, or to modify the resp_data. |
168 |
| - footer_response.send( |
169 |
| - sender=None, |
170 |
| - request=request, |
171 |
| - context=context, |
172 |
| - resp_data=resp_data, |
173 |
| - ) |
| 74 | + The methods `_get_project` and `_get_version` |
| 75 | + are called many times, so a basic cache is implemented. |
| 76 | + """ |
| 77 | + |
| 78 | + http_method_names = ['get'] |
| 79 | + permission_classes = [AllowAny] |
| 80 | + renderer_classes = [JSONRenderer, JSONPRenderer] |
| 81 | + |
| 82 | + def _get_project(self): |
| 83 | + cache_key = '_cached_project' |
| 84 | + project = getattr(self, cache_key, None) |
| 85 | + |
| 86 | + if not project: |
| 87 | + project_slug = self.request.GET.get('project', None) |
| 88 | + project = get_object_or_404(Project, slug=project_slug) |
| 89 | + setattr(self, cache_key, project) |
| 90 | + |
| 91 | + return project |
174 | 92 |
|
175 |
| - return Response(resp_data) |
| 93 | + def _get_version(self): |
| 94 | + cache_key = '_cached_version' |
| 95 | + version = getattr(self, cache_key, None) |
| 96 | + |
| 97 | + if not version: |
| 98 | + version_slug = self.request.GET.get('version', None) |
| 99 | + |
| 100 | + # Hack in a fix for missing version slug deploy |
| 101 | + # that went out a while back |
| 102 | + if version_slug == '': |
| 103 | + version_slug = LATEST |
| 104 | + |
| 105 | + version = get_object_or_404( |
| 106 | + Version.objects.public( |
| 107 | + user=self.request.user, |
| 108 | + project=self._get_project(), |
| 109 | + only_active=False, |
| 110 | + ), |
| 111 | + slug__iexact=version_slug, |
| 112 | + ) |
| 113 | + setattr(self, cache_key, version) |
| 114 | + |
| 115 | + return version |
| 116 | + |
| 117 | + def _get_context(self): |
| 118 | + theme = self.request.GET.get('theme', False) |
| 119 | + docroot = self.request.GET.get('docroot', '') |
| 120 | + subproject = self.request.GET.get('subproject', False) |
| 121 | + source_suffix = self.request.GET.get('source_suffix', '.rst') |
| 122 | + |
| 123 | + new_theme = (theme == 'sphinx_rtd_theme') |
| 124 | + using_theme = (theme == 'default') |
| 125 | + |
| 126 | + project = self._get_project() |
| 127 | + main_project = project.main_language_project or project |
| 128 | + version = self._get_version() |
| 129 | + |
| 130 | + page_slug = self.request.GET.get('page', '') |
| 131 | + if page_slug and page_slug != 'index': |
| 132 | + if main_project.documentation_type == 'sphinx_htmldir': |
| 133 | + path = page_slug + '/' |
| 134 | + else: |
| 135 | + path = page_slug + '.html' |
| 136 | + else: |
| 137 | + path = '' |
| 138 | + |
| 139 | + context = { |
| 140 | + 'project': project, |
| 141 | + 'version': version, |
| 142 | + 'path': path, |
| 143 | + 'downloads': version.get_downloads(pretty=True), |
| 144 | + 'current_version': version.verbose_name, |
| 145 | + 'versions': project.ordered_active_versions( |
| 146 | + user=self.request.user, |
| 147 | + ), |
| 148 | + 'main_project': main_project, |
| 149 | + 'translations': main_project.translations.all(), |
| 150 | + 'current_language': project.language, |
| 151 | + 'using_theme': using_theme, |
| 152 | + 'new_theme': new_theme, |
| 153 | + 'settings': settings, |
| 154 | + 'subproject': subproject, |
| 155 | + 'github_edit_url': version.get_github_url( |
| 156 | + docroot, |
| 157 | + page_slug, |
| 158 | + source_suffix, |
| 159 | + 'edit', |
| 160 | + ), |
| 161 | + 'github_view_url': version.get_github_url( |
| 162 | + docroot, |
| 163 | + page_slug, |
| 164 | + source_suffix, |
| 165 | + 'view', |
| 166 | + ), |
| 167 | + 'gitlab_edit_url': version.get_gitlab_url( |
| 168 | + docroot, |
| 169 | + page_slug, |
| 170 | + source_suffix, |
| 171 | + 'edit', |
| 172 | + ), |
| 173 | + 'gitlab_view_url': version.get_gitlab_url( |
| 174 | + docroot, |
| 175 | + page_slug, |
| 176 | + source_suffix, |
| 177 | + 'view', |
| 178 | + ), |
| 179 | + 'bitbucket_url': version.get_bitbucket_url( |
| 180 | + docroot, |
| 181 | + page_slug, |
| 182 | + source_suffix, |
| 183 | + ), |
| 184 | + 'theme': theme, |
| 185 | + } |
| 186 | + return context |
| 187 | + |
| 188 | + def get(self, request, format=None): |
| 189 | + project = self._get_project() |
| 190 | + version = self._get_version() |
| 191 | + version_compare_data = get_version_compare_data( |
| 192 | + project, |
| 193 | + version, |
| 194 | + ) |
| 195 | + |
| 196 | + context = self._get_context() |
| 197 | + html = template_loader.get_template('restapi/footer.html').render( |
| 198 | + context, |
| 199 | + request, |
| 200 | + ) |
| 201 | + |
| 202 | + resp_data = { |
| 203 | + 'html': html, |
| 204 | + 'show_version_warning': project.show_version_warning, |
| 205 | + 'version_active': version.active, |
| 206 | + 'version_compare': version_compare_data, |
| 207 | + 'version_supported': version.supported, |
| 208 | + } |
| 209 | + |
| 210 | + # Allow folks to hook onto the footer response for various information |
| 211 | + # collection, or to modify the resp_data. |
| 212 | + footer_response.send( |
| 213 | + sender=None, |
| 214 | + request=request, |
| 215 | + context=context, |
| 216 | + resp_data=resp_data, |
| 217 | + ) |
| 218 | + |
| 219 | + return Response(resp_data) |
0 commit comments