-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor footer_html view to class #6125
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,10 @@ | |
from django.conf import settings | ||
from django.shortcuts import get_object_or_404 | ||
from django.template import loader as template_loader | ||
from rest_framework import decorators, permissions | ||
from rest_framework.permissions import AllowAny | ||
from rest_framework.renderers import JSONRenderer | ||
from rest_framework.response import Response | ||
from rest_framework.views import APIView | ||
from rest_framework_jsonp.renderers import JSONPRenderer | ||
|
||
from readthedocs.api.v2.signals import footer_response | ||
|
@@ -63,113 +64,156 @@ def get_version_compare_data(project, base_version=None): | |
return ret_val | ||
|
||
|
||
@decorators.api_view(['GET']) | ||
@decorators.permission_classes((permissions.AllowAny,)) | ||
@decorators.renderer_classes((JSONRenderer, JSONPRenderer)) | ||
def footer_html(request): | ||
"""Render and return footer markup.""" | ||
# TODO refactor this function | ||
# pylint: disable=too-many-locals | ||
project_slug = request.GET.get('project', None) | ||
version_slug = request.GET.get('version', None) | ||
page_slug = request.GET.get('page', '') | ||
theme = request.GET.get('theme', False) | ||
docroot = request.GET.get('docroot', '') | ||
subproject = request.GET.get('subproject', False) | ||
source_suffix = request.GET.get('source_suffix', '.rst') | ||
|
||
# Hack in a fix for missing version slug deploy that went out a while back | ||
if version_slug == '': | ||
version_slug = LATEST | ||
|
||
new_theme = (theme == 'sphinx_rtd_theme') | ||
using_theme = (theme == 'default') | ||
project = get_object_or_404(Project, slug=project_slug) | ||
version = get_object_or_404( | ||
Version.objects.public( | ||
request.user, | ||
project=project, | ||
only_active=False, | ||
), | ||
slug__iexact=version_slug, | ||
) | ||
main_project = project.main_language_project or project | ||
class FooterHTML(APIView): | ||
|
||
if page_slug and page_slug != 'index': | ||
if main_project.documentation_type == 'sphinx_htmldir': | ||
path = page_slug + '/' | ||
else: | ||
path = page_slug + '.html' | ||
else: | ||
path = '' | ||
|
||
version_compare_data = get_version_compare_data(project, version) | ||
|
||
context = { | ||
'project': project, | ||
'version': version, | ||
'path': path, | ||
'downloads': version.get_downloads(pretty=True), | ||
'current_version': version.verbose_name, | ||
'versions': project.ordered_active_versions(user=request.user), | ||
'main_project': main_project, | ||
'translations': main_project.translations.all(), | ||
'current_language': project.language, | ||
'using_theme': using_theme, | ||
'new_theme': new_theme, | ||
'settings': settings, | ||
'subproject': subproject, | ||
'github_edit_url': version.get_github_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'edit', | ||
), | ||
'github_view_url': version.get_github_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'view', | ||
), | ||
'gitlab_edit_url': version.get_gitlab_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'edit', | ||
), | ||
'gitlab_view_url': version.get_gitlab_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'view', | ||
), | ||
'bitbucket_url': version.get_bitbucket_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
), | ||
'theme': theme, | ||
} | ||
""" | ||
Render and return footer markup. | ||
|
||
html = template_loader.get_template('restapi/footer.html').render( | ||
context, | ||
request, | ||
) | ||
resp_data = { | ||
'html': html, | ||
'show_version_warning': project.show_version_warning, | ||
'version_active': version.active, | ||
'version_compare': version_compare_data, | ||
'version_supported': version.supported, | ||
} | ||
.. note:: | ||
|
||
# Allow folks to hook onto the footer response for various information | ||
# collection, or to modify the resp_data. | ||
footer_response.send( | ||
sender=None, | ||
request=request, | ||
context=context, | ||
resp_data=resp_data, | ||
) | ||
The methods `_get_project` and `_get_version` | ||
are called many times, so a basic cache is implemented. | ||
""" | ||
|
||
http_method_names = ['get'] | ||
permission_classes = [AllowAny] | ||
renderer_classes = [JSONRenderer, JSONPRenderer] | ||
|
||
def _get_project(self): | ||
cache_key = '_cached_project' | ||
project = getattr(self, cache_key, None) | ||
stsewd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if not project: | ||
project_slug = self.request.GET.get('project', None) | ||
project = get_object_or_404(Project, slug=project_slug) | ||
setattr(self, cache_key, project) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we actually be using the real Django cache, and caching these across lookups? That would make it so we never have to hit the DB in the footer in normal cases. Probably doesn't make sense, but worth a thought. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean cache the view or the model? I'm opening a new issue to follow up. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
return project | ||
|
||
return Response(resp_data) | ||
def _get_version(self): | ||
cache_key = '_cached_version' | ||
version = getattr(self, cache_key, None) | ||
|
||
if not version: | ||
version_slug = self.request.GET.get('version', None) | ||
|
||
# Hack in a fix for missing version slug deploy | ||
# that went out a while back | ||
if version_slug == '': | ||
version_slug = LATEST | ||
|
||
version = get_object_or_404( | ||
Version.objects.public( | ||
user=self.request.user, | ||
project=self._get_project(), | ||
only_active=False, | ||
), | ||
slug__iexact=version_slug, | ||
) | ||
setattr(self, cache_key, version) | ||
|
||
return version | ||
|
||
def _get_context(self): | ||
theme = self.request.GET.get('theme', False) | ||
docroot = self.request.GET.get('docroot', '') | ||
subproject = self.request.GET.get('subproject', False) | ||
source_suffix = self.request.GET.get('source_suffix', '.rst') | ||
|
||
new_theme = (theme == 'sphinx_rtd_theme') | ||
using_theme = (theme == 'default') | ||
|
||
project = self._get_project() | ||
main_project = project.main_language_project or project | ||
version = self._get_version() | ||
|
||
page_slug = self.request.GET.get('page', '') | ||
if page_slug and page_slug != 'index': | ||
if main_project.documentation_type == 'sphinx_htmldir': | ||
path = page_slug + '/' | ||
else: | ||
path = page_slug + '.html' | ||
else: | ||
path = '' | ||
|
||
context = { | ||
'project': project, | ||
'version': version, | ||
'path': path, | ||
'downloads': version.get_downloads(pretty=True), | ||
'current_version': version.verbose_name, | ||
'versions': project.ordered_active_versions( | ||
user=self.request.user, | ||
), | ||
'main_project': main_project, | ||
'translations': main_project.translations.all(), | ||
'current_language': project.language, | ||
'using_theme': using_theme, | ||
'new_theme': new_theme, | ||
'settings': settings, | ||
'subproject': subproject, | ||
'github_edit_url': version.get_github_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'edit', | ||
), | ||
'github_view_url': version.get_github_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'view', | ||
), | ||
'gitlab_edit_url': version.get_gitlab_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'edit', | ||
), | ||
'gitlab_view_url': version.get_gitlab_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
'view', | ||
), | ||
'bitbucket_url': version.get_bitbucket_url( | ||
docroot, | ||
page_slug, | ||
source_suffix, | ||
), | ||
'theme': theme, | ||
} | ||
return context | ||
|
||
def get(self, request, format=None): | ||
project = self._get_project() | ||
version = self._get_version() | ||
version_compare_data = get_version_compare_data( | ||
project, | ||
version, | ||
) | ||
|
||
context = self._get_context() | ||
html = template_loader.get_template('restapi/footer.html').render( | ||
context, | ||
request, | ||
) | ||
|
||
resp_data = { | ||
'html': html, | ||
'show_version_warning': project.show_version_warning, | ||
'version_active': version.active, | ||
'version_compare': version_compare_data, | ||
'version_supported': version.supported, | ||
} | ||
|
||
# Allow folks to hook onto the footer response for various information | ||
# collection, or to modify the resp_data. | ||
footer_response.send( | ||
stsewd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sender=None, | ||
request=request, | ||
context=context, | ||
resp_data=resp_data, | ||
) | ||
|
||
return Response(resp_data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These cache keys should have a more specific prefix, like:
footerhtml_cached_project
. Otherwise, it's easy to override by mistake.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an attribute on the class, so it's naturally scoped I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right. We will need to change it if we move into a shared cache as you suggested, though