1 4 13 18 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 52 53 54 55 56 59 60 63 65 67 69 71 72 74 75 76 78 81 82 84 85 87 88 89 90 92 93 95 97 98 99 101 105 107 111 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 133 134 135 136 137 138 139 140 141 142 143 144 145 147 149 150 151 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 193 194 195 196 197 199 200 201 202 203 204 205 206 207 208 210 211 212 213 214 215 216 217 218 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 239 240 241 242 243 244 245 246 247 249 250 251 252 253 254 255 256 257 258 259 260 261 263 264 265 266 267 268 269 270 271 272 273 274 275 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 297 298 299 300 301 302 303 304 305 306 307 308 310 311 312 313 314 315 316 317 318 319 320 321 322 323 325 326 327 328 329 330 332 333 334 335 336 337 338 339 340 341 342 343 344 345 347 348 349 350 351 352 353 354 356 357 359 360 361 362 363 364 365 368 369 370 373 374 375 377 378 379 380 382 385 387 391 393 394 395 396 398 399 400 401 406 408 410 415 417 418 419 421 423 428 430 431 432 433 435 436 |
# -*- coding: utf-8 -*-
""" This model contain the status, dates, author, template. The real content of the page can be found in the :class:`Content <pages.models.Content>` model.
.. attribute:: creation_date When the page has been created.
.. attribute:: publication_date When the page should be visible.
.. attribute:: publication_end_date When the publication of this page end.
.. attribute:: last_modification_date Last time this page has been modified.
.. attribute:: status The current status of the page. Could be DRAFT, PUBLISHED, EXPIRED or HIDDEN. You should the property :attr:`calculated_status` if you want that the dates are taken in account.
.. attribute:: template A string containing the name of the template file for this page. """
# some class constants to refer to, e.g. Page.DRAFT (PUBLISHED, _('Published')), (HIDDEN, _('Hidden')), (DRAFT, _('Draft')), )
#PAGE_TEMPLATE_KEY = "page_%d_template" #PAGE_CHILDREN_KEY = "page_children_%d_%d"
related_name='children', verbose_name=_('parent')) default=datetime.now) null=True, blank=True, help_text=_('''When the page should go live. Status must be "Published" for page to go live.''')) null=True, blank=True, help_text=_('''When to expire the page. Leave empty to never expire.'''))
blank=True)
blank=True)
null=True, blank=True, help_text=_('''Don't publish any content after this date.'''))
# Disable could make site tests fail help_text=_('The site(s) the page is accessible at.'), verbose_name=_('sites'))
related_name='redirected_pages')
# Managers
"""Make sure the default page ordering is correct."""
"""Override the default ``save`` method.""" if not self.status: self.status = self.DRAFT # Published pages should always have a publication date if self.publication_date is None and self.status == self.PUBLISHED: self.publication_date = datetime.now() # Drafts should not, unless they have been set to the future if self.status == self.DRAFT: if settings.PAGE_SHOW_START_DATE: if (self.publication_date and self.publication_date <= datetime.now()): self.publication_date = None else: self.publication_date = None self.last_modification_date = datetime.now() # let's assume there is no more broken links after a save cache.delete(self.PAGE_BROKEN_LINK_KEY % self.id) super(Page, self).save(*args, **kwargs)
"""Get the calculated status of the page based on :attr:`Page.publication_date`, :attr:`Page.publication_end_date`, and :attr:`Page.status`.""" if settings.PAGE_SHOW_START_DATE and self.publication_date: if self.publication_date > datetime.now(): return self.DRAFT
if settings.PAGE_SHOW_END_DATE and self.publication_end_date: if self.publication_end_date < datetime.now(): return self.EXPIRED
return self.status
"""Return a :class:`QuerySet` of published children page""" return Page.objects.filter_published(self.get_children())
"""Invalidate cached data for this page."""
cache.delete(self.PAGE_LANGUAGES_KEY % (self.id)) #cache.delete(self.PAGE_TEMPLATE_KEY % (self.id))
p_names = [p.name for p in get_placeholders(self.get_template())] if 'slug' not in p_names: p_names.append('slug') if 'title' not in p_names: p_names.append('title') #frozen = int(bool(self.freeze_date)) # delete content cache, frozen or not for name in p_names: cache.delete(self.PAGE_CONTENT_DICT_KEY % (self.id, name, 1)) cache.delete(self.PAGE_CONTENT_DICT_KEY % (self.id, name, 0))
for lang in settings.PAGE_LANGUAGES: cache.delete(self.PAGE_URL_KEY % (self.id, lang[0])) cache.delete(self.PAGE_URL_KEY % (self.id, "None"))
""" Return a list of all used languages for this page. """ languages = cache.get(self.PAGE_LANGUAGES_KEY % (self.id)) if languages: return languages
languages = [c['language'] for c in Content.objects.filter(page=self, type="slug").values('language')] languages = list(set(languages)) # remove duplicates languages.sort() cache.set(self.PAGE_LANGUAGES_KEY % (self.id), languages) return languages
"""Return ``True`` if the page is the first root page.""" if self.parent: return False return Page.objects.root()[0].id == self.id
"""Return the URL's path component. Add the language prefix if ``PAGE_USE_LANGUAGE_PREFIX`` setting is set to ``True``.
:param language: the wanted url language. """ url = reverse('pages-root') if settings.PAGE_USE_LANGUAGE_PREFIX: url += str(language) + '/' return url + self.get_complete_slug(language)
"""Alias for `get_url_path`.
This method is only there for backward compatibility and will be removed in a near futur.
:param language: the wanted url language. """ return self.get_url_path(self, language=language)
"""Return the complete slug of this page by concatenating all parent's slugs.
:param language: the wanted slug language.""" url = cache.get(self.PAGE_URL_KEY % (self.id, language)) if url: return url if settings.PAGE_HIDE_ROOT_SLUG and self.is_first_root(): url = '' else: url = u'%s' % self.slug(language) for ancestor in self.get_ancestors(ascending=True): url = ancestor.slug(language) + u'/' + url
cache.set(self.PAGE_URL_KEY % (self.id, language), url)
return url
"""Alias for `get_complete_slug`.
This method is only there for backward compatibility and will be removed in a near futur.
:param language: the wanted url language. """ return self.get_complete_slug(self, language=language)
""" Return the slug of the page depending on the given language.
:param language: wanted language, if not defined default is used. :param fallback: if ``True``, the slug will also be searched in other \ languages. """
slug = Content.objects.get_content(self, language, 'slug', language_fallback=fallback)
return slug
""" Return the title of the page depending on the given language.
:param language: wanted language, if not defined default is used. :param fallback: if ``True``, the slug will also be searched in other \ languages. """ if not language: language = settings.PAGE_DEFAULT_LANGUAGE
return Content.objects.get_content(self, language, 'title', language_fallback=fallback)
""" Get the :attr:`template <Page.template>` of this page if defined or the closer parent's one if defined or :attr:`pages.settings.DEFAULT_PAGE_TEMPLATE` otherwise. """ if self.template: return self.template
template = None for p in self.get_ancestors(ascending=True): if p.template: template = p.template break
if not template: template = settings.DEFAULT_PAGE_TEMPLATE
return template
""" Get the template name of this page if defined or if a closer parent has a defined template or :data:`pages.settings.DEFAULT_PAGE_TEMPLATE` otherwise. """ template = self.get_template() page_templates = settings.get_page_templates() for t in page_templates: if t[0] == template: return t[1] return template
""" Return ``True`` if the current user has permission on the page. Return the string 'All' if the user has all rights. """ if not settings.PAGE_PERMISSION: return True else: permission = PagePermission.objects.get_page_id_list(request.user) if permission == "All": return True if self.id in permission: return True return False
""" Return ``True`` if the page have broken links to other pages into the content. """ return cache.get(self.PAGE_BROKEN_LINK_KEY % self.id)
"""Return a :class:`QuerySet` of valid targets for moving a page into the tree.
:param perms: the level of permission of the concerned user. """ exclude_list = [self.id] for p in self.get_descendants(): exclude_list.append(p.id) if perms != "All": return Page.objects.filter(id__in=perms).exclude( id__in=exclude_list) else: return Page.objects.exclude(id__in=exclude_list)
"""Display the slug of the page prepended with insecable spaces equal to the level of page in the hierarchy.""" level = '' if self.level: for n in range(0, self.level): level += ' ' return mark_safe(level + self.slug(language))
return self.level * 2
if self.id: slug = self.slug() else: return "Page %s" % self.id return slug
# Don't register the Page model twice. except mptt.AlreadyRegistered: pass
""" :class:`Page <pages.models.Page>` permission object """ (0, _('All')), (1, _('This page only')), (2, _('This page and all children')), ) verbose_name=_('page'))
return "%s :: %s" % (self.user, unicode(PagePermission.TYPES[self.type][1]))
"""A block of content, tied to a :class:`Page <pages.models.Page>`, for a particular language"""
# languages could have five characters : Brazilian Portuguese is pt-br
default=datetime.now)
return "%s :: %s" % (self.page.slug(), self.body[0:15])
"""URL alias for a :class:`Page <pages.models.Page>`""" verbose_name=_('page'))
# normalize url self.url = normalize_url(self.url) super(PageAlias, self).save(*args, **kwargs)
return "%s => %s" % (self.url, self.page.get_complete_slug())
|