mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #25916 -- Added lastmod support to sitemap index view.
Co-authored-by: Matthew Downey <matthew.downey@webit.com.au>
This commit is contained in:
committed by
Carlton Gibson
parent
2ce03a2bac
commit
480191244d
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This is a customised template -->
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
{% spaceless %}
|
||||
{% for site in sitemaps %}
|
||||
<sitemap>
|
||||
<loc>{{ site.location }}</loc>
|
||||
{% if site.last_mod %}
|
||||
<lastmod>{{ site.last_mod|date:"c" }}</lastmod>
|
||||
{% endif %}
|
||||
</sitemap>
|
||||
{% endfor %}
|
||||
{% endspaceless %}
|
||||
</sitemapindex>
|
||||
@@ -85,3 +85,12 @@ class GenericViewsSitemapTests(SitemapTestsBase):
|
||||
)
|
||||
with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
|
||||
sitemap.get_protocol()
|
||||
|
||||
def test_generic_sitemap_index(self):
|
||||
TestModel.objects.update(lastmod=datetime(2013, 3, 13, 10, 0, 0))
|
||||
response = self.client.get('/generic-lastmod/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>http://example.com/simple/sitemap-generic.xml</loc><lastmod>2013-03-13T10:00:00</lastmod></sitemap>
|
||||
</sitemapindex>"""
|
||||
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
|
||||
|
||||
@@ -24,9 +24,9 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/simple/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url
|
||||
""" % (self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_sitemap_not_callable(self):
|
||||
@@ -34,9 +34,9 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/simple-not-callable/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url
|
||||
""" % (self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_paged_sitemap(self):
|
||||
@@ -44,24 +44,24 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/simple-paged/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>{0}/simple/sitemap-simple.xml</loc></sitemap><sitemap><loc>{0}/simple/sitemap-simple.xml?p=2</loc></sitemap>
|
||||
<sitemap><loc>{0}/simple/sitemap-simple.xml</loc><lastmod>{1}</lastmod></sitemap><sitemap><loc>{0}/simple/sitemap-simple.xml?p=2</loc><lastmod>{1}</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""".format(self.base_url)
|
||||
""".format(self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
@override_settings(TEMPLATES=[{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
|
||||
}])
|
||||
def test_simple_sitemap_custom_index(self):
|
||||
def test_simple_sitemap_custom_lastmod_index(self):
|
||||
"A simple sitemap index can be rendered with a custom template"
|
||||
response = self.client.get('/simple/custom-index.xml')
|
||||
response = self.client.get('/simple/custom-lastmod-index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This is a customised template -->
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url
|
||||
""" % (self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_simple_sitemap_section(self):
|
||||
@@ -176,7 +176,30 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/lastmod-sitemaps/descending.xml')
|
||||
self.assertEqual(response.headers['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT')
|
||||
|
||||
@override_settings(USE_I18N=True)
|
||||
def test_sitemap_get_latest_lastmod_none(self):
|
||||
"""
|
||||
sitemapindex.lastmod is ommitted when Sitemap.lastmod is
|
||||
callable and Sitemap.get_latest_lastmod is not implemented
|
||||
"""
|
||||
response = self.client.get('/lastmod/get-latest-lastmod-none-sitemap.xml')
|
||||
self.assertNotContains(response, '<lastmod>')
|
||||
|
||||
def test_sitemap_get_latest_lastmod(self):
|
||||
"""
|
||||
sitemapindex.lastmod is included when Sitemap.lastmod is
|
||||
attribute and Sitemap.get_latest_lastmod is implemented
|
||||
"""
|
||||
response = self.client.get('/lastmod/get-latest-lastmod-sitemap.xml')
|
||||
self.assertContains(response, '<lastmod>2013-03-13T10:00:00</lastmod>')
|
||||
|
||||
def test_sitemap_latest_lastmod_timezone(self):
|
||||
"""
|
||||
lastmod datestamp shows timezones if Sitemap.get_latest_lastmod
|
||||
returns an aware datetime.
|
||||
"""
|
||||
response = self.client.get('/lastmod/latest-lastmod-timezone-sitemap.xml')
|
||||
self.assertContains(response, '<lastmod>2013-03-13T10:00:00-05:00</lastmod>')
|
||||
|
||||
def test_localized_priority(self):
|
||||
"""The priority value should not be localized."""
|
||||
with translation.override('fr'):
|
||||
@@ -240,9 +263,9 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/cached/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/cached/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/cached/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url
|
||||
""" % (self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_x_robots_sitemap(self):
|
||||
@@ -356,7 +379,7 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
def test_callable_sitemod_partial(self):
|
||||
"""
|
||||
Not all items have `lastmod`. Therefore the `Last-Modified` header
|
||||
is not set by the detail sitemap view.
|
||||
is not set by the detail or index sitemap view.
|
||||
"""
|
||||
index_response = self.client.get('/callable-lastmod-partial/index.xml')
|
||||
sitemap_response = self.client.get('/callable-lastmod-partial/sitemap.xml')
|
||||
@@ -378,16 +401,15 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
def test_callable_sitemod_full(self):
|
||||
"""
|
||||
All items in the sitemap have `lastmod`. The `Last-Modified` header
|
||||
is set for the detail sitemap view. The index view does not (currently)
|
||||
set the `Last-Modified` header.
|
||||
is set for the detail and index sitemap view.
|
||||
"""
|
||||
index_response = self.client.get('/callable-lastmod-full/index.xml')
|
||||
sitemap_response = self.client.get('/callable-lastmod-full/sitemap.xml')
|
||||
self.assertNotIn('Last-Modified', index_response)
|
||||
self.assertEqual(index_response.headers['Last-Modified'], 'Thu, 13 Mar 2014 10:00:00 GMT')
|
||||
self.assertEqual(sitemap_response.headers['Last-Modified'], 'Thu, 13 Mar 2014 10:00:00 GMT')
|
||||
expected_content_index = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>http://example.com/simple/sitemap-callable-lastmod.xml</loc></sitemap>
|
||||
<sitemap><loc>http://example.com/simple/sitemap-callable-lastmod.xml</loc><lastmod>2014-03-13T10:00:00</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
"""
|
||||
expected_content_sitemap = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -397,3 +419,31 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||
"""
|
||||
self.assertXMLEqual(index_response.content.decode(), expected_content_index)
|
||||
self.assertXMLEqual(sitemap_response.content.decode(), expected_content_sitemap)
|
||||
|
||||
|
||||
# RemovedInDjango50Warning
|
||||
class DeprecatedTests(SitemapTestsBase):
|
||||
@override_settings(TEMPLATES=[{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
|
||||
}])
|
||||
def test_simple_sitemap_custom_index_warning(self):
|
||||
msg = 'Calling `__str__` on SitemapIndexItem is deprecated, use the `location` attribute instead.'
|
||||
with self.assertRaisesMessage(RemovedInDjango50Warning, msg):
|
||||
self.client.get('/simple/custom-index.xml')
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||
@override_settings(TEMPLATES=[{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
|
||||
}])
|
||||
def test_simple_sitemap_custom_index(self):
|
||||
"A simple sitemap index can be rendered with a custom template"
|
||||
response = self.client.get('/simple/custom-index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This is a customised template -->
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
|
||||
</sitemapindex>
|
||||
""" % (self.base_url)
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
@@ -14,9 +14,9 @@ class HTTPSSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/secure/index.xml')
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/secure/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/secure/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url
|
||||
""" % (self.base_url, date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_secure_sitemap_section(self):
|
||||
@@ -39,9 +39,9 @@ class HTTPSDetectionSitemapTests(SitemapTestsBase):
|
||||
response = self.client.get('/simple/index.xml', **self.extra)
|
||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
|
||||
<sitemap><loc>%s/simple/sitemap-simple.xml</loc><lastmod>%s</lastmod></sitemap>
|
||||
</sitemapindex>
|
||||
""" % self.base_url.replace('http://', 'https://')
|
||||
""" % (self.base_url.replace('http://', 'https://'), date.today())
|
||||
self.assertXMLEqual(response.content.decode(), expected_content)
|
||||
|
||||
def test_sitemap_section_with_https_request(self):
|
||||
|
||||
@@ -14,13 +14,15 @@ class SimpleSitemap(Sitemap):
|
||||
changefreq = "never"
|
||||
priority = 0.5
|
||||
location = '/location/'
|
||||
lastmod = datetime.now()
|
||||
lastmod = date.today()
|
||||
|
||||
def items(self):
|
||||
return [object()]
|
||||
|
||||
|
||||
class SimplePagedSitemap(Sitemap):
|
||||
lastmod = date.today()
|
||||
|
||||
def items(self):
|
||||
return [object() for x in range(Sitemap.limit + 1)]
|
||||
|
||||
@@ -110,6 +112,26 @@ class CallableLastmodFullSitemap(Sitemap):
|
||||
return obj.lastmod
|
||||
|
||||
|
||||
class GetLatestLastmodNoneSiteMap(Sitemap):
|
||||
changefreq = "never"
|
||||
priority = 0.5
|
||||
location = '/location/'
|
||||
|
||||
def items(self):
|
||||
return [object()]
|
||||
|
||||
def lastmod(self, obj):
|
||||
return datetime(2013, 3, 13, 10, 0, 0)
|
||||
|
||||
def get_latest_lastmod(self):
|
||||
return None
|
||||
|
||||
|
||||
class GetLatestLastmodSiteMap(SimpleSitemap):
|
||||
def get_latest_lastmod(self):
|
||||
return datetime(2013, 3, 13, 10, 0, 0)
|
||||
|
||||
|
||||
def testmodelview(request, id):
|
||||
return HttpResponse()
|
||||
|
||||
@@ -180,6 +202,18 @@ generic_sitemaps = {
|
||||
'generic': GenericSitemap({'queryset': TestModel.objects.order_by('pk').all()}),
|
||||
}
|
||||
|
||||
get_latest_lastmod_none_sitemaps = {
|
||||
'get-latest-lastmod-none': GetLatestLastmodNoneSiteMap,
|
||||
}
|
||||
|
||||
get_latest_lastmod_sitemaps = {
|
||||
'get-latest-lastmod': GetLatestLastmodSiteMap,
|
||||
}
|
||||
|
||||
latest_lastmod_timezone_sitemaps = {
|
||||
'latest-lastmod-timezone': TimezoneSiteMap,
|
||||
}
|
||||
|
||||
generic_sitemaps_lastmod = {
|
||||
'generic': GenericSitemap({
|
||||
'queryset': TestModel.objects.order_by('pk').all(),
|
||||
@@ -202,6 +236,10 @@ urlpatterns = [
|
||||
path(
|
||||
'simple/custom-index.xml', views.index,
|
||||
{'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap_index.xml'}),
|
||||
path(
|
||||
'simple/custom-lastmod-index.xml', views.index,
|
||||
{'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap_lastmod_index.xml'},
|
||||
),
|
||||
path(
|
||||
'simple/sitemap-<section>.xml', views.sitemap,
|
||||
{'sitemaps': simple_sitemaps},
|
||||
@@ -266,6 +304,21 @@ urlpatterns = [
|
||||
'lastmod-sitemaps/descending.xml', views.sitemap,
|
||||
{'sitemaps': sitemaps_lastmod_descending},
|
||||
name='django.contrib.sitemaps.views.sitemap'),
|
||||
path(
|
||||
'lastmod/get-latest-lastmod-none-sitemap.xml', views.index,
|
||||
{'sitemaps': get_latest_lastmod_none_sitemaps},
|
||||
name='django.contrib.sitemaps.views.index',
|
||||
),
|
||||
path(
|
||||
'lastmod/get-latest-lastmod-sitemap.xml', views.index,
|
||||
{'sitemaps': get_latest_lastmod_sitemaps},
|
||||
name='django.contrib.sitemaps.views.index',
|
||||
),
|
||||
path(
|
||||
'lastmod/latest-lastmod-timezone-sitemap.xml', views.index,
|
||||
{'sitemaps': latest_lastmod_timezone_sitemaps},
|
||||
name='django.contrib.sitemaps.views.index',
|
||||
),
|
||||
path(
|
||||
'generic/sitemap.xml', views.sitemap,
|
||||
{'sitemaps': generic_sitemaps},
|
||||
@@ -287,6 +340,11 @@ urlpatterns = [
|
||||
path('callable-lastmod-partial/sitemap.xml', views.sitemap, {'sitemaps': callable_lastmod_partial_sitemap}),
|
||||
path('callable-lastmod-full/index.xml', views.index, {'sitemaps': callable_lastmod_full_sitemap}),
|
||||
path('callable-lastmod-full/sitemap.xml', views.sitemap, {'sitemaps': callable_lastmod_full_sitemap}),
|
||||
path(
|
||||
'generic-lastmod/index.xml', views.index,
|
||||
{'sitemaps': generic_sitemaps_lastmod},
|
||||
name='django.contrib.sitemaps.views.index',
|
||||
),
|
||||
]
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
|
||||
Reference in New Issue
Block a user