Skip to content

Commit 1f1fc2d

Browse files
committed
Added static views to sitemap.
1 parent fc43b71 commit 1f1fc2d

File tree

5 files changed

+112
-28
lines changed

5 files changed

+112
-28
lines changed

djangoproject/sitemaps.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from dataclasses import dataclass
2+
3+
from django.contrib import sitemaps
4+
from django_hosts.resolvers import reverse
5+
6+
7+
@dataclass
8+
class URLObject:
9+
name: str
10+
host: str = "www"
11+
12+
13+
class LocationAbsoluteUrlMixin:
14+
def get_urls(self, site=None, **kwargs):
15+
"""
16+
Prevent the Django sitemap framework from prefixing the domain.
17+
Use the absolute URL returned by location().
18+
"""
19+
urls = []
20+
for item in self.items():
21+
loc = self.location(item)
22+
urls.append(
23+
{
24+
"location": loc,
25+
"lastmod": None,
26+
"changefreq": self.changefreq,
27+
"priority": self.priority,
28+
}
29+
)
30+
return urls
31+
32+
33+
class StaticViewSitemap(LocationAbsoluteUrlMixin, sitemaps.Sitemap):
34+
priority = 0.5
35+
changefreq = "monthly"
36+
37+
def items(self):
38+
return [
39+
# accounts
40+
URLObject("registration_register"),
41+
# aggregator
42+
URLObject("community-index"),
43+
URLObject("community-ecosystem"),
44+
URLObject("local-django-communities"),
45+
# contact
46+
URLObject("contact_foundation"),
47+
# dashboard
48+
URLObject("dashboard-index", host="dashboard"),
49+
URLObject("metric-list", host="dashboard"),
50+
# djangoproject
51+
URLObject("homepage"),
52+
URLObject("overview"),
53+
URLObject("start"),
54+
URLObject("code_of_conduct"),
55+
URLObject("conduct_faq"),
56+
URLObject("conduct_reporting"),
57+
URLObject("conduct_enforcement"),
58+
URLObject("conduct_changes"),
59+
URLObject("diversity"),
60+
URLObject("diversity_changes"),
61+
# foundation
62+
URLObject("foundation_meeting_archive_index"),
63+
# fundraising
64+
URLObject("fundraising:index"),
65+
# members
66+
URLObject("members:individual-members"),
67+
URLObject("members:corporate-members"),
68+
URLObject("members:corporate-members-join"),
69+
URLObject("members:corporate-members-badges"),
70+
URLObject("members:teams"),
71+
# releases
72+
URLObject("download"),
73+
]
74+
75+
def location(self, item):
76+
return reverse(item.name, host=item.host)

djangoproject/tests.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def test_single_h1_per_page(self):
202202
"styleguide/", # Has multiple <h1> examples.
203203
"admin/", # Admin templates are out of our control.
204204
"reset/done/", # Uses an admin template.
205+
"sitemap.xml",
205206
]
206207
resolver = get_resolver()
207208
urls = self.extract_patterns(resolver.url_patterns)
@@ -211,3 +212,9 @@ def test_single_h1_per_page(self):
211212
response = self.client.get(url)
212213
self.assertEqual(response.status_code, 200)
213214
self.assertContains(response, "<h1", count=1)
215+
216+
217+
class SiteMapTests(TestCase):
218+
def test_sitemap_renders(self):
219+
response = self.client.get(reverse("sitemap"))
220+
self.assertEqual(response.status_code, 200)

djangoproject/urls/www.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from aggregator.feeds import CommunityAggregatorFeed, CommunityAggregatorFirehoseFeed
1414
from blog.feeds import WeblogEntryFeed
1515
from blog.sitemaps import WeblogSitemap
16+
from djangoproject.sitemaps import StaticViewSitemap
1617
from foundation.feeds import FoundationMinutesFeed
1718
from foundation.views import CoreDevelopers
1819

@@ -21,6 +22,7 @@
2122
sitemaps = {
2223
"weblog": WeblogSitemap,
2324
"flatpages": FlatPageSitemap,
25+
"static": StaticViewSitemap,
2426
}
2527

2628

@@ -135,6 +137,7 @@
135137
"sitemap.xml",
136138
cache_page(60 * 60 * 6)(sitemap_views.sitemap),
137139
{"sitemaps": sitemaps},
140+
name="sitemap",
138141
),
139142
path("weblog/", include("blog.urls")),
140143
path("download/", include("releases.urls")),

docs/sitemaps.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from django.contrib.sitemaps import Sitemap
22

3+
from djangoproject.sitemaps import LocationAbsoluteUrlMixin
4+
35
from .models import Document
46
from .search import DocumentationCategory
57

68

7-
class DocsSitemap(Sitemap):
9+
class DocsSitemap(LocationAbsoluteUrlMixin, Sitemap):
810
def __init__(self, lang):
911
self.lang = lang
1012

@@ -16,6 +18,9 @@ def items(self):
1618
.select_related("release__release")
1719
)
1820

21+
def location(self, item):
22+
return item.get_absolute_url()
23+
1924
def changefreq(self, obj):
2025
return "daily"
2126

@@ -33,19 +38,3 @@ def priority(self, obj):
3338
return 1
3439
else:
3540
return 0.1
36-
37-
def _urls(self, page, site, protocol):
38-
# XXX: To workaround bad interaction between contrib.sitemaps and
39-
# django-hosts (scheme/domain would be repeated twice in URLs)
40-
urls = []
41-
for item in self.paginator.page(page).object_list:
42-
loc = item.get_absolute_url()
43-
priority = self.priority(item)
44-
url_info = {
45-
"item": item,
46-
"location": loc,
47-
"changefreq": self.changefreq(item),
48-
"priority": str(priority if priority is not None else ""),
49-
}
50-
urls.append(url_info)
51-
return urls

docs/tests/test_models.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
from django.db import connection
88
from django.test import TestCase
99
from django.utils import timezone
10+
from django_hosts import reverse
1011

1112
from blog.models import ContentFormat, Entry
13+
from djangoproject.sitemaps import StaticViewSitemap
1214
from releases.models import Release
1315

1416
from ..models import Document, DocumentRelease
@@ -605,7 +607,7 @@ def test_sync_to_db_not_delete_website_docs(self):
605607

606608
def test_sync_from_sitemap_skip_non_en_dev_release(self):
607609
release = Release.objects.create(version="5.2")
608-
Entry.objects.create(
610+
blog_entry = Entry.objects.create(
609611
pub_date=timezone.now() - datetime.timedelta(days=2),
610612
slug="a",
611613
body="<strong>test</strong>",
@@ -623,7 +625,16 @@ def test_sync_from_sitemap_skip_non_en_dev_release(self):
623625
)
624626
with self.subTest(lang=lang, release=release_obj):
625627
doc_release.sync_from_sitemap()
626-
self.assertFalse(Document.objects.exists())
628+
self.assertFalse(
629+
Document.objects.filter(path=blog_entry.get_absolute_url()).exists()
630+
)
631+
632+
@staticmethod
633+
def _mock_static_sitemap_urls(mocker):
634+
sitemap = StaticViewSitemap()
635+
for item in sitemap.items():
636+
url = reverse(item.name, host=item.host)
637+
mocker.get(url, text="", headers={"Content-Type": "text/html"})
627638

628639
@requests_mock.mock()
629640
def test_sync_from_sitemap(self, mocker):
@@ -634,17 +645,16 @@ def test_sync_from_sitemap(self, mocker):
634645
content_format=ContentFormat.HTML,
635646
is_active=True,
636647
)
648+
self._mock_static_sitemap_urls(mocker)
637649
mocker.get(
638650
blog_entry.get_absolute_url(),
639651
text="<html><main>Main 1</main><h1>Title 1</h1></html>",
640652
headers={"Content-Type": "text/html"},
641653
)
642654
self.release.sync_from_sitemap()
643655

644-
document = Document.objects.get(release=self.release)
645-
self.assertEqual(
646-
document.path,
647-
blog_entry.get_absolute_url(),
656+
document = Document.objects.get(
657+
release=self.release, path=blog_entry.get_absolute_url()
648658
)
649659
self.assertEqual(
650660
document.title,
@@ -681,12 +691,10 @@ def test_sync_from_sitemap_only_requests_non_existing(self, mock_fetch_html):
681691

682692
mock_fetch_html.assert_not_called()
683693

684-
document = Document.objects.get(release=self.release)
685-
# Confirm Document has not been updated.
686-
self.assertEqual(
687-
document.path,
688-
blog_entry.get_absolute_url(),
694+
document = Document.objects.get(
695+
release=self.release, path=blog_entry.get_absolute_url()
689696
)
697+
# Confirm Document has not been updated.
690698
self.assertEqual(
691699
document.metadata,
692700
{"parents": DocumentationCategory.WEBSITE},
@@ -712,6 +720,7 @@ def test_sync_from_sitemap_force(self, mocker):
712720
metadata={"parents": DocumentationCategory.WEBSITE},
713721
path=blog_url,
714722
)
723+
self._mock_static_sitemap_urls(mocker)
715724
mocker.get(
716725
blog_url,
717726
text="<html><main>Main 1</main><h1>Title 1</h1></html>",

0 commit comments

Comments
 (0)