[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
This commit is contained in:
Tim Graham 2014-09-09 13:34:40 -04:00
parent d321218a52
commit 7de55fa68e
4 changed files with 39 additions and 2 deletions

View File

@ -82,6 +82,21 @@ class HTTPSitemapTests(SitemapTestsBase):
response = self.client.get('/lastmod/sitemap.xml') response = self.client.get('/lastmod/sitemap.xml')
self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT') 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): def test_sitemap_last_modified_missing(self):
"Tests that Last-Modified header is missing when sitemap has no lastmod" "Tests that Last-Modified header is missing when sitemap has no lastmod"
response = self.client.get('/generic/sitemap.xml') response = self.client.get('/generic/sitemap.xml')

View File

@ -1,6 +1,7 @@
from datetime import datetime from datetime import date, datetime
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views
from django.utils import timezone
from django.views.decorators.cache import cache_page from django.views.decorators.cache import cache_page
from django.contrib.sitemaps.tests.base import TestModel from django.contrib.sitemaps.tests.base import TestModel
@ -42,6 +43,14 @@ class FixedLastmodMixedSitemap(Sitemap):
return [o1, o2] 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_sitemaps = {
'simple': SimpleSitemap, 'simple': SimpleSitemap,
} }
@ -78,6 +87,10 @@ urlpatterns = patterns('django.contrib.sitemaps.views',
(r'^empty/sitemap\.xml$', 'sitemap', {'sitemaps': empty_sitemaps}), (r'^empty/sitemap\.xml$', 'sitemap', {'sitemaps': empty_sitemaps}),
(r'^lastmod/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod_sitemaps}), (r'^lastmod/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod_sitemaps}),
(r'^lastmod-mixed/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod__mixed_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'^generic/sitemap\.xml$', 'sitemap', {'sitemaps': generic_sitemaps}),
(r'^flatpages/sitemap\.xml$', 'sitemap', {'sitemaps': flatpage_sitemaps}), (r'^flatpages/sitemap\.xml$', 'sitemap', {'sitemaps': flatpage_sitemaps}),
url(r'^cached/index\.xml$', cache_page(1)(views.index), url(r'^cached/index\.xml$', cache_page(1)(views.index),

View File

@ -1,4 +1,5 @@
from calendar import timegm from calendar import timegm
import datetime
from functools import wraps from functools import wraps
from django.contrib.sites.shortcuts import get_current_site 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 hasattr(site, 'latest_lastmod'):
# if latest_lastmod is defined for site, set header so as # if latest_lastmod is defined for site, set header so as
# ConditionalGetMiddleware is able to send 304 NOT MODIFIED # ConditionalGetMiddleware is able to send 304 NOT MODIFIED
lastmod = site.latest_lastmod
response['Last-Modified'] = http_date( response['Last-Modified'] = http_date(
timegm(site.latest_lastmod.utctimetuple())) timegm(
lastmod.utctimetuple() if isinstance(lastmod, datetime.datetime)
else lastmod.timetuple()
)
)
return response return response

View File

@ -40,3 +40,6 @@ Bugfixes
* Empty ``index_together`` or ``unique_together`` model options no longer * Empty ``index_together`` or ``unique_together`` model options no longer
results in infinite migrations (:ticket:`23452`). results in infinite migrations (:ticket:`23452`).
* Fixed crash in ``contrib.sitemaps`` if ``lastmod`` returned a ``date`` rather
than a ``datetime`` (:ticket:`23403`).