Loading django/contrib/sitemaps/__init__.py +11 −1 Original line number Diff line number Diff line Loading @@ -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): Loading django/contrib/sitemaps/tests/test_http.py +15 −0 Original line number Diff line number Diff line Loading @@ -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): Loading django/contrib/sitemaps/tests/urls/http.py +28 −0 Original line number Diff line number Diff line Loading @@ -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()}), } Loading @@ -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), Loading django/contrib/sitemaps/views.py +10 −2 Original line number Diff line number Diff line from calendar import timegm from functools import wraps from django.contrib.sites.models import get_current_site Loading @@ -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) Loading Loading @@ -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}, 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 docs/ref/contrib/sitemaps.txt +9 −0 Original line number Diff line number Diff line Loading @@ -178,6 +178,15 @@ Sitemap class reference representing the last-modified date/time for *every* object returned by :attr:`~Sitemap.items()`. .. versionadded:: 1.7 If all items in a sitemap have a :attr:`~Sitemap.lastmod`, the sitemap generated by :func:`views.sitemap` will have a ``Last-Modified`` header equal to the latest ``lastmod``. You can activate the :class:`~django.middleware.http.ConditionalGetMiddleware` to make Django respond appropriately to requests with an ``If-Modified-Since`` header which will prevent sending the sitemap if it hasn't changed. .. attribute:: Sitemap.changefreq **Optional.** Either a method or attribute. Loading Loading
django/contrib/sitemaps/__init__.py +11 −1 Original line number Diff line number Diff line Loading @@ -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): Loading
django/contrib/sitemaps/tests/test_http.py +15 −0 Original line number Diff line number Diff line Loading @@ -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): Loading
django/contrib/sitemaps/tests/urls/http.py +28 −0 Original line number Diff line number Diff line Loading @@ -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()}), } Loading @@ -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), Loading
django/contrib/sitemaps/views.py +10 −2 Original line number Diff line number Diff line from calendar import timegm from functools import wraps from django.contrib.sites.models import get_current_site Loading @@ -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) Loading Loading @@ -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}, 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
docs/ref/contrib/sitemaps.txt +9 −0 Original line number Diff line number Diff line Loading @@ -178,6 +178,15 @@ Sitemap class reference representing the last-modified date/time for *every* object returned by :attr:`~Sitemap.items()`. .. versionadded:: 1.7 If all items in a sitemap have a :attr:`~Sitemap.lastmod`, the sitemap generated by :func:`views.sitemap` will have a ``Last-Modified`` header equal to the latest ``lastmod``. You can activate the :class:`~django.middleware.http.ConditionalGetMiddleware` to make Django respond appropriately to requests with an ``If-Modified-Since`` header which will prevent sending the sitemap if it hasn't changed. .. attribute:: Sitemap.changefreq **Optional.** Either a method or attribute. Loading