dynamicweb/cms/utils/page.py

146 lines
4.5 KiB
Python

import re
from django.urls import NoReverseMatch, reverse
from django.utils.encoding import force_str
from cms.constants import PAGE_USERNAME_MAX_LENGTH
from cms.utils import get_current_site, get_language_from_request
from cms.utils.conf import get_cms_setting
SUFFIX_REGEX = re.compile(r'^(.*)-(\d+)$')
def get_page_template_from_request(request):
"""
Gets a valid template from different sources or falls back to the default
template.
"""
templates = get_cms_setting('TEMPLATES')
template_names = frozenset(pair[0] for pair in templates)
if not templates:
# no templates defined, CMS is running headless
return None
if len(templates) == 1:
# there's only one template
# avoid any further computation
return templates[0][0]
manual_template = request.GET.get('template')
if manual_template and manual_template in template_names:
return manual_template
if request.current_page:
return request.current_page.get_template()
return get_cms_setting('TEMPLATES')[0][0]
def get_clean_username(user):
try:
username = force_str(user)
except AttributeError:
# AnonymousUser may not have USERNAME_FIELD
username = "anonymous"
else:
# limit changed_by and created_by to avoid problems with Custom User Model
if len(username) > PAGE_USERNAME_MAX_LENGTH:
username = f'{username[:PAGE_USERNAME_MAX_LENGTH - 15]}... (id={user.pk})'
return username
def get_page_queryset(site, draft=True, published=False): # pragma: no cover
from warnings import warn
from cms.models import Page
from cms.utils.compat.warnings import RemovedInDjangoCMS60Warning
warn(
"cms.utils.page.get_page_queryset is deprecated. "
"Use Page.objects.on_site(site) instead.",
RemovedInDjangoCMS60Warning,
stacklevel=2,
)
return Page.objects.on_site(site)
def get_page_from_request(request, use_path=None, clean_path=None):
"""
Gets the current page from a request object.
URLs can be of the following form (this should help understand the code):
http://server.whatever.com/<some_path>/"pages-root"/some/page/slug
<some_path>: This can be anything, and should be stripped when resolving
pages names. This means the CMS is not installed at the root of the
server's URLs.
"pages-root" This is the root of Django urls for the CMS. It is, in essence
an empty page slug (slug == '')
The page slug can then be resolved to a Page model object
"""
from cms.models import PageUrl
if hasattr(request, '_current_page_cache'):
# The following is set by CurrentPageMiddleware
return request._current_page_cache
if clean_path is None:
clean_path = not bool(use_path)
path = request.path_info if use_path is None else use_path
if clean_path:
try:
pages_root = reverse("pages-root")
if path.startswith(pages_root):
path = path[len(pages_root):]
# strip any final slash
if path.endswith("/"):
path = path[:-1]
except NoReverseMatch:
pass
site = get_current_site(request)
page_urls = (
PageUrl
.objects
.get_for_site(site)
.filter(path=path)
.select_related("page", "page__site")
)
page_urls = list(page_urls) # force queryset evaluation to save 1 query
try:
page = page_urls[0].page
if page_urls[0].language == get_language_from_request(request):
page.urls_cache = {url.language: url for url in page_urls}
except IndexError:
page = None
return page
def get_available_slug(site, path, language, suffix='copy', modified=False):
"""
Generates slug for path.
If path is used, appends the value of suffix to the end.
"""
from cms.models.pagemodel import PageUrl
base, _, slug = path.rpartition('/')
page_urls = PageUrl.objects.get_for_site(site, path=path, language=language)
if page_urls.exists():
match = SUFFIX_REGEX.match(slug)
if match and modified:
_next = int(match.groups()[-1]) + 1
slug = SUFFIX_REGEX.sub(f'\\g<1>-{_next}', slug)
elif suffix:
slug += '-' + suffix + '-2'
else:
slug += '-2'
path = f'{base}/{slug}' if base else slug
return get_available_slug(site, path, language, suffix, modified=True)
return slug