dynamicweb/cms/page_rendering.py

98 lines
3.6 KiB
Python

from django.conf import settings
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import Resolver404, resolve, reverse
from cms import __version__, constants
from cms.cache.page import set_page_cache
from cms.models import EmptyPageContent
from cms.utils.page_permissions import user_can_change_page, user_can_view_page
from cms.utils.urlutils import admin_reverse
def render_page(request, page, current_language, slug=None):
"""
Renders a page
"""
page_content = page.page_content_cache.get(current_language, page.get_content_obj(current_language))
context = {}
context['lang'] = current_language
context['current_page'] = page
context['current_pagecontent'] = page_content
context['has_change_permissions'] = user_can_change_page(request.user, page)
context['has_view_permissions'] = user_can_view_page(request.user, page)
cant_view_page = any([
not context['has_view_permissions'],
isinstance(page_content, EmptyPageContent)
])
if cant_view_page:
return _handle_no_page(request)
template = page_content.get_template()
if not template:
# Render placeholder content with minimal markup
from cms.views import render_placeholder_content
return render_placeholder_content(request, page_content, context)
response = TemplateResponse(request, template, context)
response.add_post_render_callback(set_page_cache)
# Add headers for X Frame Options - this really should be changed upon moving to class based views
xframe_options = page.get_xframe_options()
# xframe_options can be None if there's no xframe information on the page
# (eg. a top-level page which has xframe options set to "inherit")
if xframe_options == constants.X_FRAME_OPTIONS_INHERIT or xframe_options is None:
# This is when we defer to django's own clickjacking handling
return response
# We want to prevent django setting this in their middleware
response.xframe_options_exempt = True
if xframe_options == constants.X_FRAME_OPTIONS_ALLOW:
# Do nothing, allowed is no header.
return response
elif xframe_options == constants.X_FRAME_OPTIONS_SAMEORIGIN:
response['X-Frame-Options'] = 'SAMEORIGIN'
elif xframe_options == constants.X_FRAME_OPTIONS_DENY:
response['X-Frame-Options'] = 'DENY'
return response
def _handle_no_page(request):
try:
match = resolve(request.path)
except Resolver404 as e:
raise Http404(dict(path=request.path, tried=e.args[0]['tried'])) from e
# redirect to PageContent's changelist if the root page is detected
if match.url_name == 'pages-root':
try:
redirect_url = admin_reverse('cms_pagecontent_changelist')
return HttpResponseRedirect(redirect_url)
except Resolver404:
pass
raise Http404(dict(path=request.path, tried=match.tried))
def _handle_no_apphook(request):
context = {
"absolute_url": request.toolbar.request_path,
}
return TemplateResponse(request, "cms/noapphook.html", context)
def _render_welcome_page(request):
context = {
'cms_version': __version__,
'django_debug': settings.DEBUG,
'next_url': reverse('pages-root'),
}
return TemplateResponse(request, "cms/welcome.html", context)
def render_pagecontent(request, pagecontent):
language = pagecontent.language
request.current_page = page = pagecontent.page
page.page_content_cache[language] = pagecontent
return render_page(request, page, language)