diff mbox series

[layerindex-web,2/2] Add sitemap using django.contrib.sitemaps

Message ID 20261008142738.29958-2-tim.orling@konsulko.com
State New
Headers show
Series [layerindex-web,1/2] layerindex/views: fix publishing layers with multiple branches | expand

Commit Message

Tim Orling Oct. 8, 2026, 2:27 p.m. UTC
From: Michael Halstead <mhalstead@linuxfoundation.org>

Serve /sitemap.xml listing the main branch views and all published,
non-comparison layers.

AI-Generated: Claude Sonnet 5.5
Signed-off-by: Michael Halstead <mhalstead@linuxfoundation.org>
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 docker/settings.py     |  1 +
 layerindex/sitemaps.py | 36 ++++++++++++++++++++++++++++++++++++
 settings.py            |  1 +
 tests/test_sitemap.py  | 38 ++++++++++++++++++++++++++++++++++++++
 urls.py                |  9 +++++++++
 5 files changed, 85 insertions(+)
 create mode 100644 layerindex/sitemaps.py
 create mode 100644 tests/test_sitemap.py
diff mbox series

Patch

diff --git a/docker/settings.py b/docker/settings.py
index e3ae0fd..90bc5f4 100644
--- a/docker/settings.py
+++ b/docker/settings.py
@@ -148,6 +148,7 @@  INSTALLED_APPS = (
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
+    'django.contrib.sitemaps',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'django.contrib.admin',
diff --git a/layerindex/sitemaps.py b/layerindex/sitemaps.py
new file mode 100644
index 0000000..7d6e0ac
--- /dev/null
+++ b/layerindex/sitemaps.py
@@ -0,0 +1,36 @@ 
+# layerindex-web - sitemap definitions
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+from django.contrib.sitemaps import Sitemap
+from django.urls import reverse
+
+from layerindex.models import LayerItem
+
+BRANCH_VIEWS = ('layer_list', 'recipe_search', 'machine_search', 'distro_search', 'class_search')
+
+
+class StaticViewSitemap(Sitemap):
+    changefreq = 'daily'
+    priority = 0.5
+
+    def items(self):
+        return list(BRANCH_VIEWS) + ['about', 'stats']
+
+    def location(self, item):
+        if item in BRANCH_VIEWS:
+            return reverse(item, args=('master',))
+        return reverse(item)
+
+
+class LayerSitemap(Sitemap):
+    changefreq = 'weekly'
+    priority = 0.8
+
+    def items(self):
+        return LayerItem.objects.filter(status='P', comparison=False).order_by('name')
+
+    def lastmod(self, obj):
+        return obj.updated
diff --git a/settings.py b/settings.py
index 94b3dd1..b318687 100644
--- a/settings.py
+++ b/settings.py
@@ -148,6 +148,7 @@  INSTALLED_APPS = (
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
+    'django.contrib.sitemaps',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'django.contrib.admin',
diff --git a/tests/test_sitemap.py b/tests/test_sitemap.py
new file mode 100644
index 0000000..12b4b87
--- /dev/null
+++ b/tests/test_sitemap.py
@@ -0,0 +1,38 @@ 
+# layerindex-web - tests for sitemap.xml
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import pytest
+from django.test import TestCase
+
+from layerindex.models import LayerItem
+
+
+@pytest.mark.django_db
+class TestSitemap(TestCase):
+
+    def _layer(self, name, status='P', comparison=False):
+        return LayerItem.objects.create(
+            name=name,
+            status=status,
+            layer_type='A',
+            summary=name,
+            description=name,
+            vcs_url='git://example.com/%s.git' % name,
+            comparison=comparison,
+        )
+
+    def test_sitemap(self):
+        self._layer('meta-published')
+        self._layer('meta-new', status='N')
+        self._layer('meta-compare', comparison=True)
+
+        response = self.client.get('/sitemap.xml')
+        self.assertEqual(response.status_code, 200)
+        content = response.content.decode()
+        self.assertIn('/layerindex/branch/master/layer/meta-published/', content)
+        self.assertIn('/layerindex/about/', content)
+        self.assertNotIn('meta-new', content)
+        self.assertNotIn('meta-compare', content)
diff --git a/urls.py b/urls.py
index 295fc0b..4bd5998 100644
--- a/urls.py
+++ b/urls.py
@@ -12,13 +12,22 @@  from django.views.generic import RedirectView, TemplateView
 from layerindex.auth_views import CaptchaRegistrationView, CaptchaPasswordResetView, delete_account_view, \
     PasswordResetSecurityQuestions
 from django.contrib import admin
+from django.contrib.sitemaps.views import sitemap
+from layerindex.sitemaps import StaticViewSitemap, LayerSitemap
 admin.autodiscover()
 
 from django.conf import settings
 
+sitemaps = {
+    'static': StaticViewSitemap,
+    'layers': LayerSitemap,
+}
+
 urlpatterns = [
     re_path(r'^layerindex/', include('layerindex.urls')),
     re_path(r'^admin/', admin.site.urls),
+    re_path(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
+        name='django.contrib.sitemaps.views.sitemap'),
     re_path(r'^accounts/password_reset/$',
         CaptchaPasswordResetView.as_view(
             email_template_name='registration/password_reset_email.txt',