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
|
# ------------------------------------------------------------------------
# coding=utf-8
# ------------------------------------------------------------------------
from django.db.models import Max
from django.contrib.sitemaps import Sitemap
from feincms.module.page.models import Page
# ------------------------------------------------------------------------
class PageSitemap(Sitemap):
"""
The PageSitemap can be used to automatically generate sitemap.xml files
for submission to index engines. See http://www.sitemaps.org/ for details.
"""
def __init__(self, navigation_only=False, max_depth=0, changefreq=None, queryset=None, filter=None, extended_navigation=False, *args, **kwargs):
"""
The PageSitemap accepts the following parameters for customisation
of the resulting sitemap.xml output:
* navigation_only -- if set to True, only pages that are in_navigation
will appear in the site map.
* max_depth -- if set to a non-negative integer, will limit the sitemap
generated to this page hierarchy depth.
* changefreq -- should be a string or callable specifiying the page
update frequency, according to the sitemap protocol.
* queryset -- pass in a query set to restrict the Pages to include
in the site map.
* filter -- pass in a callable that transforms a queryset to filter
out the pages you want to include in the site map.
* extended_navigation -- if set to True, adds pages from any navigation
extensions. If using PagePretender, make sure to include title, url,
level, in_navigation and optionally modification_date.
"""
super(PageSitemap, self).__init__(*args, **kwargs)
self.depth_cutoff = max_depth
self.navigation_only = navigation_only
self.changefreq = changefreq
self.filter = filter
self.extended_navigation = extended_navigation
if queryset is not None:
self.queryset = queryset
else:
self.queryset = Page.objects.active()
def items(self):
"""
Consider all pages that are active and that are not a redirect
"""
base_qs = self.queryset
if callable(base_qs):
base_qs = base_qs()
self.max_depth = base_qs.aggregate(Max('level'))['level__max']
if self.depth_cutoff > 0:
self.max_depth = min(self.depth_cutoff, self.max_depth)
self.per_level = 1.0 / (self.max_depth + 1.0)
qs = base_qs.filter(redirect_to="")
if self.filter:
qs = self.filter(qs)
if self.navigation_only:
qs = qs.filter(in_navigation=True)
if self.depth_cutoff > 0:
qs = qs.filter(level__lte=self.max_depth-1)
pages = [ p for p in qs if p.is_active() ]
if self.extended_navigation:
for idx, page in enumerate(pages):
if getattr(page, 'navigation_extension', None):
pages[idx + 1:idx + 1] = page.extended_navigation()
return pages
def lastmod(self, obj):
return getattr(obj, 'modification_date', None)
# the priority is computed of the depth in the tree of a page
# may we should make an extension to give control to the user for priority
def priority(self, obj):
"""
The priority is staggered according to the depth of the page in
the site. Top level get highest priority, then each level is decreased
by per_level.
"""
prio = 1.0 - (obj.level + 1) * self.per_level
# If the page is in_navigation, then it's more important, so boost
# its importance
if obj.in_navigation:
prio += 1.2 * self.per_level
return "%0.2g" % min(1.0, prio)
# After a call to the sitemap, be sure to erase the cached _paginator
# attribute, so next time we'll re-fetch the items list instead of using
# a stale list.
# This has been fixed in Django r17468
def get_urls(self, *args, **kwargs):
urls = super(PageSitemap, self).get_urls(*args, **kwargs)
if hasattr(self, '_paginator'):
del(self._paginator)
return urls
# ------------------------------------------------------------------------
|