-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
page.py
137 lines (106 loc) · 4.04 KB
/
page.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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
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):
from cms.models import Page
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()
page_urls = (
PageUrl
.objects
.get_for_site(site)
.filter(path=path)
.select_related('page')
)
page_urls = list(page_urls) # force queryset evaluation to save 1 query
try:
page = page_urls[0].page
except IndexError:
page = None
else:
page.urls_cache = {url.language: url for url in page_urls}
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