[geany/www.geany.org] 6a3ccf: Rewrite Sitemap generation: include static and dynamic items from other apps

Enrico Tröger git-noreply at xxxxx
Sun Aug 9 11:27:13 UTC 2015


Branch:      refs/heads/master
Author:      Enrico Tröger <enrico.troeger at uvena.de>
Committer:   Enrico Tröger <enrico.troeger at uvena.de>
Date:        Sun, 09 Aug 2015 11:27:13 UTC
Commit:      6a3ccf22a2d57bcbf59f076ab2904c02ec36f42b
             https://github.com/geany/www.geany.org/commit/6a3ccf22a2d57bcbf59f076ab2904c02ec36f42b

Log Message:
-----------
Rewrite Sitemap generation: include static and dynamic items from other apps

Now the generated sitemap.xml includes static items from the LatestVersion and
News apps. While static items are generated are only once for the application
lifetime, dynamic items are generated on each request.


Modified Paths:
--------------
    geany/settings.py
    geany/sitemaps.py
    latest_version/urls.py
    nightlybuilds/urls.py
    pastebin/urls.py

Modified: geany/settings.py
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -169,6 +169,9 @@
 SESSION_EXPIRE_AT_BROWSER_CLOSE = True
 
 SITE_ID = 1
+SITE_DOMAIN_WWW = 'www.geany.org'
+SITE_DOMAIN_PASTEBIN = 'pastebin.geany.org'
+SITE_DOMAIN_NIGHTLY = 'nightly.geany.org'
 
 # If you set this to False, Django will make some optimizations so as not
 # to load the internationalization machinery.


Modified: geany/sitemaps.py
141 lines changed, 125 insertions(+), 16 deletions(-)
===================================================================
@@ -16,28 +16,79 @@
 from django.contrib.sites.models import Site
 from django.core import urlresolvers
 from django_hosts.resolvers import get_host
-from mezzanine.blog.models import BlogPost
+from mezzanine.conf import settings
 from mezzanine.core.sitemaps import DisplayableSitemap
 
+"""
+Sitemap generation
+GeanyMainSitemap is the main class which generates sitemap items
+for all Mezzaine pages, blog posts, News posts and various static
+items.
+
+Other apps might add their own sitemap generator classes to the
+"sitemap_registry" provided by this module. For performance reasons,
+static sitemap items (i.e. items generated from URLconf patterns) are
+generated already on module-level because they never changed during
+the whole application lifetime.
+In addition, dynamic items (such as Pages and news posts) are added to
+the static items at runtime as they may change at any time.
+"""
+
 
 ########################################################################
-class GeanyDisplayableSitemap(DisplayableSitemap):
+class GeanyMainSitemap(DisplayableSitemap):
     """
     Sitemap class for Django's sitemaps framework that returns
     all published items for models that subclass ``Displayable``.
     """
     changefreq = 'monthly'
+    priority = 0.5
+
+    #----------------------------------------------------------------------
+    def items(self):
+        items = super(GeanyMainSitemap, self).items()
+        additional_app_items = self._get_additional_app_items()
+        items.extend(additional_app_items)
+        return items
+
+    #----------------------------------------------------------------------
+    def _get_additional_app_items(self):
+        return sitemap_registry.get_all_items()
 
     #----------------------------------------------------------------------
     def lastmod(self, obj):
         return obj.publish_date
 
+
+########################################################################
+class SitemapItem(object):
+    """Simulate a model, mainly to provide get_absolute_url() for Sitemaps"""
+
     #----------------------------------------------------------------------
-    def priority(self, obj):
-        if isinstance(obj, BlogPost):
-            return 1
-        else:
-            return 0.5
+    def __init__(self, name, absolute_url, publish_date=None, priority=0.5):
+        self._name = name
+        self._absolute_url = absolute_url
+        self._publish_date = publish_date
+        self._priority = priority
+
+    #----------------------------------------------------------------------
+    def get_absolute_url(self):
+        return self._absolute_url
+
+    #----------------------------------------------------------------------
+    @property
+    def name(self):
+        return self._name
+
+    #----------------------------------------------------------------------
+    @property
+    def publish_date(self):
+        return self._publish_date
+
+    #----------------------------------------------------------------------
+    @property
+    def priority(self):
+        return self._priority
 
 
 ########################################################################
@@ -51,14 +102,17 @@ def __init__(self, domain, patterns):
         self._patterns = patterns
         self._site = None
         self._host = None
-        self._items = {}
+        self._url_mapping = {}
         self._get_site_and_host()
-        self._initialize()
 
     #----------------------------------------------------------------------
-    def _get_site_and_host(self):
-        self._site = Site.objects.get(domain=self._domain)
-        self._host = get_host(self._domain)
+    def items(self):
+        return self.get_static_items() + self.get_dynamic_items()
+
+    #----------------------------------------------------------------------
+    def get_static_items(self):
+        self._initialize()
+        return [SitemapItem(name, url) for name, url in self._url_mapping.items()]
 
     #----------------------------------------------------------------------
     def _initialize(self):
@@ -66,7 +120,12 @@ def _initialize(self):
             if getattr(pattern, 'name', None) is not None:
                 url_resolved = self._resolve_url(pattern.name)
                 if url_resolved:
-                    self._items[pattern.name] = url_resolved
+                    self._url_mapping[pattern.name] = url_resolved
+
+    #----------------------------------------------------------------------
+    def _get_site_and_host(self):
+        self._site = Site.objects.get(domain=self._domain)
+        self._host = get_host(self._domain)
 
     #----------------------------------------------------------------------
     def _resolve_url(self, url):
@@ -76,8 +135,8 @@ def _resolve_url(self, url):
             return None
 
     #----------------------------------------------------------------------
-    def items(self):
-        return self._items.keys()
+    def get_dynamic_items(self):
+        return list()
 
     #----------------------------------------------------------------------
     def changefreq(self, obj):
@@ -85,9 +144,59 @@ def changefreq(self, obj):
 
     #----------------------------------------------------------------------
     def location(self, obj):
-        return self._items[obj]
+        return self._url_mapping[obj.name]
 
     #----------------------------------------------------------------------
     def get_urls(self, page=1, site=None, protocol=None):
         # pass our site to the parent as we know better which site we are on
         return super(StaticSitemap, self).get_urls(page, self._site, protocol)
+
+
+########################################################################
+class SitemapRegistry(object):
+
+    #----------------------------------------------------------------------
+    def __init__(self):
+        self._sitemap_generators = list()
+        self._static_items = None
+
+    #----------------------------------------------------------------------
+    def add(self, generator_class, url_patterns, site_domain=None):
+        if site_domain is None:
+            site_domain = settings.SITE_DOMAIN_WWW
+        sitemap_generator_item = (generator_class, url_patterns, site_domain)
+        self._sitemap_generators.append(sitemap_generator_item)
+
+    #----------------------------------------------------------------------
+    def _update_static_sitemap_items(self, sitemap_generator_class, url_patterns, site_domain):
+        generator = sitemap_generator_class(site_domain, url_patterns)
+        items = generator.get_static_items()
+        self._static_items.extend(items)
+
+    #----------------------------------------------------------------------
+    def get_all_items(self):
+        if self._static_items is None:
+            self._static_items = self._get_static_items()
+        dynamic_items = self._get_dynamic_items()
+        return self._static_items + dynamic_items
+
+    #----------------------------------------------------------------------
+    def _get_static_items(self):
+        static_items = list()
+        for sitemap_generator_class, url_patterns, site_domain in self._sitemap_generators:
+            generator = sitemap_generator_class(site_domain, url_patterns)
+            items = generator.get_static_items()
+            static_items.extend(items)
+        return static_items
+
+    #----------------------------------------------------------------------
+    def _get_dynamic_items(self):
+        dynamic_items = list()
+        for sitemap_generator_class, url_patterns, site_domain in self._sitemap_generators:
+            generator = sitemap_generator_class(site_domain, url_patterns)
+            items = generator.get_dynamic_items()
+            dynamic_items.extend(items)
+        return dynamic_items
+
+
+sitemap_registry = SitemapRegistry()


Modified: latest_version/urls.py
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -14,6 +14,7 @@
 
 from django.conf.urls import patterns, url
 from django.views.generic import TemplateView
+from geany.sitemaps import StaticSitemap, sitemap_registry
 
 
 urlpatterns = patterns('',
@@ -27,3 +28,6 @@
 # Adds ``STATIC_URL`` to the context of error pages, so that error pages can use JS, CSS and images.
 handler404 = "mezzanine.core.views.page_not_found"
 handler500 = "mezzanine.core.views.server_error"
+
+# register our urlpatterns to the global sitemap generator
+sitemap_registry.add(StaticSitemap, urlpatterns)


Modified: nightlybuilds/urls.py
12 lines changed, 10 insertions(+), 2 deletions(-)
===================================================================
@@ -12,9 +12,10 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from django.conf.urls import url, patterns
-from nightlybuilds.views import NightlyBuildsView
+from django.conf import settings
+from django.conf.urls import include, patterns, url
 from geany.sitemaps import StaticSitemap
+from nightlybuilds.views import NightlyBuildsView
 
 
 urlpatterns = patterns('',
@@ -24,6 +25,13 @@
     url(r'^$', NightlyBuildsView.as_view(), name='home'),
 )
 
+# Django-Debug-Toolbar support
+if settings.DEBUG:
+    import debug_toolbar
+    urlpatterns += patterns('',
+        url(r'^__debug__/', include(debug_toolbar.urls)),
+    )
+
 # Sitemap framework
 sitemaps = {"sitemaps": {"all": StaticSitemap('nightly.geany.org', urlpatterns)}}
 urlpatterns += patterns('',


Modified: pastebin/urls.py
12 lines changed, 10 insertions(+), 2 deletions(-)
===================================================================
@@ -13,7 +13,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-from django.conf.urls import url, patterns
+from django.conf import settings
+from django.conf.urls import include, patterns, url
 from django.views.generic.base import TemplateView
 from geany.sitemaps import StaticSitemap
 from pastebin.views import (
@@ -41,8 +42,15 @@
     url(r'^(?P<snippet_id>[a-zA-Z0-9]+)/raw/$', SnippetDetailRawView.as_view(), name='snippet_details_raw'),
 )
 
+# Django-Debug-Toolbar support
+if settings.DEBUG:
+    import debug_toolbar
+    urlpatterns += patterns('',
+        url(r'^__debug__/', include(debug_toolbar.urls)),
+    )
+
 # Sitemap framework
-sitemaps = {"sitemaps": {"all": StaticSitemap('pastebin.geany.org', urlpatterns)}}
+sitemaps = {"sitemaps": {"all": StaticSitemap(settings.SITE_DOMAIN_PASTEBIN, urlpatterns)}}
 urlpatterns += patterns('',
     # use our custom sitemap implementation
     url(r"^sitemap\.xml$", 'django.contrib.sitemaps.views.sitemap', sitemaps)



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list