Skip to content

Commit 34d1a15

Browse files
authored
Merge pull request #6125 from stsewd/stsewd/refactor-footer-html-view
Refactor footer_html view to class
2 parents 00ab116 + 9c5cf6f commit 34d1a15

File tree

3 files changed

+155
-111
lines changed

3 files changed

+155
-111
lines changed

readthedocs/api/v2/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
function_urls = [
5858
url(r'docurl/', core_views.docurl, name='docurl'),
59-
url(r'footer_html/', footer_views.footer_html, name='footer_html'),
59+
url(r'footer_html/', footer_views.FooterHTML.as_view(), name='footer_html'),
6060
]
6161

6262
task_urls = [

readthedocs/api/v2/views/footer_views.py

Lines changed: 151 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
from django.conf import settings
44
from django.shortcuts import get_object_or_404
55
from django.template import loader as template_loader
6-
from rest_framework import decorators, permissions
6+
from rest_framework.permissions import AllowAny
77
from rest_framework.renderers import JSONRenderer
88
from rest_framework.response import Response
9+
from rest_framework.views import APIView
910
from rest_framework_jsonp.renderers import JSONPRenderer
1011

1112
from readthedocs.api.v2.signals import footer_response
@@ -63,113 +64,156 @@ def get_version_compare_data(project, base_version=None):
6364
return ret_val
6465

6566

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):
9768

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.
15371
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::
16573
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
17492

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)

readthedocs/rtd_tests/tests/test_footer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from rest_framework.test import APIRequestFactory, APITestCase
55

66
from readthedocs.api.v2.views.footer_views import (
7-
footer_html,
7+
FooterHTML,
88
get_version_compare_data,
99
)
1010
from readthedocs.builds.constants import BRANCH, LATEST, TAG
@@ -26,7 +26,7 @@ def setUpTestData(cls):
2626

2727
def render(self):
2828
request = self.factory.get(self.url)
29-
response = footer_html(request)
29+
response = FooterHTML.as_view()(request)
3030
response.render()
3131
return response
3232

@@ -243,7 +243,7 @@ def setUp(self):
243243

244244
def render(self):
245245
request = self.factory.get(self.url)
246-
response = footer_html(request)
246+
response = FooterHTML.as_view()(request)
247247
response.render()
248248
return response
249249

0 commit comments

Comments
 (0)