summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorJulian Bez <julian.bez@uhura.de>2013-07-23 16:25:21 +0200
committerTim Graham <timograham@gmail.com>2013-07-31 07:42:30 -0400
commit8f5533ab250df07ea84f98d39808806e282468a5 (patch)
treeea9c02f76acd0129d28b2688ec33463beda446a4 /django
parent4d8ecbdfda4da95685a2a51906425c6baa58a09f (diff)
Fixed #20793 -- Added Last-Modified header to sitemaps.
Diffstat (limited to 'django')
-rw-r--r--django/contrib/sitemaps/__init__.py12
-rw-r--r--django/contrib/sitemaps/tests/test_http.py15
-rw-r--r--django/contrib/sitemaps/tests/urls/http.py28
-rw-r--r--django/contrib/sitemaps/views.py12
4 files changed, 64 insertions, 3 deletions
diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py
index 1acae8296c..627813a33e 100644
--- a/django/contrib/sitemaps/__init__.py
+++ b/django/contrib/sitemaps/__init__.py
@@ -86,17 +86,27 @@ class Sitemap(object):
domain = site.domain
urls = []
+ latest_lastmod = None
+ all_items_lastmod = True # track if all items have a lastmod
for item in self.paginator.page(page).object_list:
loc = "%s://%s%s" % (protocol, domain, self.__get('location', item))
priority = self.__get('priority', item, None)
+ lastmod = self.__get('lastmod', item, None)
+ if all_items_lastmod:
+ all_items_lastmod = lastmod is not None
+ if (all_items_lastmod and
+ (latest_lastmod is None or lastmod > latest_lastmod)):
+ latest_lastmod = lastmod
url_info = {
'item': item,
'location': loc,
- 'lastmod': self.__get('lastmod', item, None),
+ 'lastmod': lastmod,
'changefreq': self.__get('changefreq', item, None),
'priority': str(priority if priority is not None else ''),
}
urls.append(url_info)
+ if all_items_lastmod:
+ self.latest_lastmod = latest_lastmod
return urls
class FlatPageSitemap(Sitemap):
diff --git a/django/contrib/sitemaps/tests/test_http.py b/django/contrib/sitemaps/tests/test_http.py
index f68f345815..c870b442de 100644
--- a/django/contrib/sitemaps/tests/test_http.py
+++ b/django/contrib/sitemaps/tests/test_http.py
@@ -77,6 +77,21 @@ class HTTPSitemapTests(SitemapTestsBase):
""" % (self.base_url, date.today())
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
+ def test_sitemap_last_modified(self):
+ "Tests that Last-Modified header is set correctly"
+ response = self.client.get('/lastmod/sitemap.xml')
+ self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT')
+
+ def test_sitemap_last_modified_missing(self):
+ "Tests that Last-Modified header is missing when sitemap has no lastmod"
+ response = self.client.get('/generic/sitemap.xml')
+ self.assertFalse(response.has_header('Last-Modified'))
+
+ def test_sitemap_last_modified_mixed(self):
+ "Tests that Last-Modified header is omitted when lastmod not on all items"
+ response = self.client.get('/lastmod-mixed/sitemap.xml')
+ self.assertFalse(response.has_header('Last-Modified'))
+
@skipUnless(settings.USE_I18N, "Internationalization is not enabled")
@override_settings(USE_L10N=True)
def test_localized_priority(self):
diff --git a/django/contrib/sitemaps/tests/urls/http.py b/django/contrib/sitemaps/tests/urls/http.py
index a8b804fd4b..6721d72b81 100644
--- a/django/contrib/sitemaps/tests/urls/http.py
+++ b/django/contrib/sitemaps/tests/urls/http.py
@@ -15,10 +15,36 @@ class SimpleSitemap(Sitemap):
def items(self):
return [object()]
+
+class FixedLastmodSitemap(SimpleSitemap):
+ lastmod = datetime(2013, 3, 13, 10, 0, 0)
+
+
+class FixedLastmodMixedSitemap(Sitemap):
+ changefreq = "never"
+ priority = 0.5
+ location = '/location/'
+ loop = 0
+
+ def items(self):
+ o1 = TestModel()
+ o1.lastmod = datetime(2013, 3, 13, 10, 0, 0)
+ o2 = TestModel()
+ return [o1, o2]
+
+
simple_sitemaps = {
'simple': SimpleSitemap,
}
+fixed_lastmod_sitemaps = {
+ 'fixed-lastmod': FixedLastmodSitemap,
+}
+
+fixed_lastmod__mixed_sitemaps = {
+ 'fixed-lastmod-mixed': FixedLastmodMixedSitemap,
+}
+
generic_sitemaps = {
'generic': GenericSitemap({'queryset': TestModel.objects.all()}),
}
@@ -36,6 +62,8 @@ urlpatterns = patterns('django.contrib.sitemaps.views',
(r'^simple/sitemap\.xml$', 'sitemap', {'sitemaps': simple_sitemaps}),
(r'^simple/custom-sitemap\.xml$', 'sitemap',
{'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
+ (r'^lastmod/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod_sitemaps}),
+ (r'^lastmod-mixed/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod__mixed_sitemaps}),
(r'^generic/sitemap\.xml$', 'sitemap', {'sitemaps': generic_sitemaps}),
(r'^flatpages/sitemap\.xml$', 'sitemap', {'sitemaps': flatpage_sitemaps}),
url(r'^cached/index\.xml$', cache_page(1)(views.index),
diff --git a/django/contrib/sitemaps/views.py b/django/contrib/sitemaps/views.py
index 7a94fb355d..14983acea9 100644
--- a/django/contrib/sitemaps/views.py
+++ b/django/contrib/sitemaps/views.py
@@ -1,3 +1,4 @@
+from calendar import timegm
from functools import wraps
from django.contrib.sites.models import get_current_site
@@ -6,6 +7,7 @@ from django.core.paginator import EmptyPage, PageNotAnInteger
from django.http import Http404
from django.template.response import TemplateResponse
from django.utils import six
+from django.utils.http import http_date
def x_robots_tag(func):
@wraps(func)
@@ -64,5 +66,11 @@ def sitemap(request, sitemaps, section=None,
raise Http404("Page %s empty" % page)
except PageNotAnInteger:
raise Http404("No page '%s'" % page)
- return TemplateResponse(request, template_name, {'urlset': urls},
- content_type=content_type)
+ response = TemplateResponse(request, template_name, {'urlset': urls},
+ content_type=content_type)
+ if hasattr(site, 'latest_lastmod'):
+ # if latest_lastmod is defined for site, set header so as
+ # ConditionalGetMiddleware is able to send 304 NOT MODIFIED
+ response['Last-Modified'] = http_date(
+ timegm(site.latest_lastmod.utctimetuple()))
+ return response