Skip to content

Commit df4137e

Browse files
committed
Adds feeds sitemap
Extends the sitemap to include feeds for global regions (continents and oceans). This allows search engines to discover and crawl the regional feeds. Also updates the version number.
1 parent d9ff893 commit df4137e

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

optimap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.8.0"
1+
__version__ = "0.9.0"
22
VERSION = __version__

optimap/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
from django.contrib import admin
1717
from django.urls import path, re_path, include
1818
from django.contrib.sitemaps import views as sitemaps_views
19-
from publications.sitemaps import PublicationsSitemap, StaticViewSitemap
19+
from publications.sitemaps import PublicationsSitemap, StaticViewSitemap, FeedsSitemap
2020
from publications.views import RobotsView
2121

2222
sitemaps = {
2323
"static": StaticViewSitemap,
2424
"publications": PublicationsSitemap,
25+
"feeds": FeedsSitemap,
2526
}
2627

2728
urlpatterns = [

publications/sitemaps.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.contrib.sitemaps import Sitemap
2-
from .models import Publication
2+
from .models import Publication, GlobalRegion
33
from django.urls import reverse
44

55

@@ -47,4 +47,21 @@ def items(self):
4747
]
4848

4949
def location(self, item):
50-
return reverse(f"optimap:{item}")
50+
return reverse(f"optimap:{item}")
51+
52+
class FeedsSitemap(Sitemap):
53+
"""Sitemap for global regional feeds (continents and oceans)."""
54+
priority = 0.6
55+
changefreq = "daily"
56+
57+
def items(self):
58+
"""Return all GlobalRegion objects (continents and oceans)."""
59+
return GlobalRegion.objects.all().order_by('region_type', 'name')
60+
61+
def location(self, obj):
62+
"""Return the feed page URL for each region."""
63+
return obj.get_absolute_url()
64+
65+
def lastmod(self, obj):
66+
"""Return the last modification date."""
67+
return obj.last_loaded

tests/test_sitemap.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.test import TestCase
2+
from django.contrib.gis.geos import MultiPolygon, Polygon
23
from http import HTTPStatus
4+
from publications.models import GlobalRegion
35

46
class SitemapTest(TestCase):
57
def test_index(self):
@@ -17,3 +19,73 @@ def test_publications(self):
1719
self.assertEqual(response.status_code, HTTPStatus.OK)
1820
self.assertEqual(response["content-type"], "application/xml")
1921
# TODO test content
22+
23+
def test_feeds(self):
24+
"""Test feeds sitemap generation for global regions."""
25+
response = self.client.get("/sitemap-feeds.xml")
26+
self.assertEqual(response.status_code, HTTPStatus.OK)
27+
self.assertEqual(response["content-type"], "application/xml")
28+
29+
def test_feeds_content(self):
30+
"""Test feeds sitemap includes regional feed URLs."""
31+
# Create test GlobalRegion instances
32+
test_polygon = MultiPolygon(Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))))
33+
34+
continent = GlobalRegion.objects.create(
35+
name="Test Continent",
36+
region_type=GlobalRegion.CONTINENT,
37+
source_url="http://example.com",
38+
license="CC BY 4.0",
39+
geom=test_polygon
40+
)
41+
42+
ocean = GlobalRegion.objects.create(
43+
name="Test Ocean",
44+
region_type=GlobalRegion.OCEAN,
45+
source_url="http://example.com",
46+
license="CC BY 4.0",
47+
geom=test_polygon
48+
)
49+
50+
# Get the feeds sitemap
51+
response = self.client.get("/sitemap-feeds.xml")
52+
content = response.content.decode('utf-8')
53+
54+
# Verify response
55+
self.assertEqual(response.status_code, HTTPStatus.OK)
56+
self.assertIn('<?xml version="1.0" encoding="UTF-8"?>', content)
57+
self.assertIn('<urlset', content)
58+
59+
# Verify continent feed URL is included
60+
self.assertIn('/feeds/continent/test-continent/', content)
61+
62+
# Verify ocean feed URL is included
63+
self.assertIn('/feeds/ocean/test-ocean/', content)
64+
65+
# Verify priority and changefreq
66+
self.assertIn('<priority>0.6</priority>', content)
67+
self.assertIn('<changefreq>daily</changefreq>', content)
68+
69+
def test_feeds_index_reference(self):
70+
"""Test that feeds sitemap is referenced in main sitemap index.
71+
72+
Note: Django's sitemap index only includes sitemaps that have items.
73+
This test creates GlobalRegion objects to ensure the feeds sitemap
74+
appears in the index.
75+
"""
76+
# Create at least one GlobalRegion so the feeds sitemap has items
77+
test_polygon = MultiPolygon(Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))))
78+
GlobalRegion.objects.create(
79+
name="Test Region",
80+
region_type=GlobalRegion.CONTINENT,
81+
source_url="http://example.com",
82+
license="CC BY 4.0",
83+
geom=test_polygon
84+
)
85+
86+
response = self.client.get("/sitemap.xml")
87+
content = response.content.decode('utf-8')
88+
89+
self.assertEqual(response.status_code, HTTPStatus.OK)
90+
# Verify the feeds sitemap is listed in the index
91+
self.assertIn('sitemap-feeds.xml', content)

0 commit comments

Comments
 (0)