From 7de55fa68e694b84e5ea9c383d87153b5be0d43a Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 9 Sep 2014 13:34:40 -0400 Subject: [PATCH] [1.7.x] Fixed #23403 -- Fixed crash in contrib.sitemaps if lastmod returned a date rather than datetime. Thanks igorcc for the report and Preston Timmons for review. Backport of 66580fe97c from master --- django/contrib/sitemaps/tests/test_http.py | 15 +++++++++++++++ django/contrib/sitemaps/tests/urls/http.py | 15 ++++++++++++++- django/contrib/sitemaps/views.py | 8 +++++++- docs/releases/1.7.1.txt | 3 +++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/django/contrib/sitemaps/tests/test_http.py b/django/contrib/sitemaps/tests/test_http.py index 2f9ebd8fad..b524afc7e3 100644 --- a/django/contrib/sitemaps/tests/test_http.py +++ b/django/contrib/sitemaps/tests/test_http.py @@ -82,6 +82,21 @@ class HTTPSitemapTests(SitemapTestsBase): 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_date(self): + """ + The Last-Modified header should be support dates (without time). + """ + response = self.client.get('/lastmod/date-sitemap.xml') + self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 00:00:00 GMT') + + def test_sitemap_last_modified_tz(self): + """ + The Last-Modified header should be converted from timezone aware dates + to GMT. + """ + response = self.client.get('/lastmod/tz-sitemap.xml') + self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 15: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') diff --git a/django/contrib/sitemaps/tests/urls/http.py b/django/contrib/sitemaps/tests/urls/http.py index 2cadb23deb..237f9baf3e 100644 --- a/django/contrib/sitemaps/tests/urls/http.py +++ b/django/contrib/sitemaps/tests/urls/http.py @@ -1,6 +1,7 @@ -from datetime import datetime +from datetime import date, datetime from django.conf.urls import patterns, url from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views +from django.utils import timezone from django.views.decorators.cache import cache_page from django.contrib.sitemaps.tests.base import TestModel @@ -42,6 +43,14 @@ class FixedLastmodMixedSitemap(Sitemap): return [o1, o2] +class DateSiteMap(SimpleSitemap): + lastmod = date(2013, 3, 13) + + +class TimezoneSiteMap(SimpleSitemap): + lastmod = datetime(2013, 3, 13, 10, 0, 0, tzinfo=timezone.get_fixed_timezone(-300)) + + simple_sitemaps = { 'simple': SimpleSitemap, } @@ -78,6 +87,10 @@ urlpatterns = patterns('django.contrib.sitemaps.views', (r'^empty/sitemap\.xml$', 'sitemap', {'sitemaps': empty_sitemaps}), (r'^lastmod/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod_sitemaps}), (r'^lastmod-mixed/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod__mixed_sitemaps}), + url(r'^lastmod/date-sitemap.xml$', views.sitemap, + {'sitemaps': {'date-sitemap': DateSiteMap}}), + url(r'^lastmod/tz-sitemap.xml$', views.sitemap, + {'sitemaps': {'tz-sitemap': TimezoneSiteMap}}), (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 aa184e99bd..a743f6e614 100644 --- a/django/contrib/sitemaps/views.py +++ b/django/contrib/sitemaps/views.py @@ -1,4 +1,5 @@ from calendar import timegm +import datetime from functools import wraps from django.contrib.sites.shortcuts import get_current_site @@ -74,6 +75,11 @@ def sitemap(request, sitemaps, section=None, if hasattr(site, 'latest_lastmod'): # if latest_lastmod is defined for site, set header so as # ConditionalGetMiddleware is able to send 304 NOT MODIFIED + lastmod = site.latest_lastmod response['Last-Modified'] = http_date( - timegm(site.latest_lastmod.utctimetuple())) + timegm( + lastmod.utctimetuple() if isinstance(lastmod, datetime.datetime) + else lastmod.timetuple() + ) + ) return response diff --git a/docs/releases/1.7.1.txt b/docs/releases/1.7.1.txt index 98e99e8125..8e45850437 100644 --- a/docs/releases/1.7.1.txt +++ b/docs/releases/1.7.1.txt @@ -40,3 +40,6 @@ Bugfixes * Empty ``index_together`` or ``unique_together`` model options no longer results in infinite migrations (:ticket:`23452`). + +* Fixed crash in ``contrib.sitemaps`` if ``lastmod`` returned a ``date`` rather + than a ``datetime`` (:ticket:`23403`).