Ticket #8995: https_sitemaps.diff

File https_sitemaps.diff, 13.0 KB (added by John Hensley, 13 years ago)

Patch to support HTTPS URLs in sitemaps

  • django/contrib/sitemaps/__init__.py

    commit a30d3a02a852d82b442a218c526a0a1fdfe2c861
    Author: John Hensley <john@fairviewcomputing.com>
    Date:   Tue Jun 28 11:03:35 2011 -0400
    
        Support HTTPS in sitemaps.
    
    diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py
    index 98ab353..5161da1 100644
    a b class Sitemap(object):  
    3939    # This limit is defined by Google. See the index documentation at
    4040    # http://sitemaps.org/protocol.php#index.
    4141    limit = 50000
     42    protocol = 'http'
    4243
    4344    def __get(self, name, obj, default=None):
    4445        try:
    class Sitemap(object):  
    7374
    7475        urls = []
    7576        for item in self.paginator.page(page).object_list:
    76             loc = "http://%s%s" % (site.domain, self.__get('location', item))
     77            loc = "%s://%s%s" % (self.protocol, site.domain, self.__get('location', item))
    7778            priority = self.__get('priority', item, None)
    7879            url_info = {
    7980                'item':       item,
  • django/contrib/sitemaps/tests/__init__.py

    diff --git a/django/contrib/sitemaps/tests/__init__.py b/django/contrib/sitemaps/tests/__init__.py
    index c5b483c..be28c8f 100644
    a b  
    11from django.contrib.sitemaps.tests.basic import *
     2from django.contrib.sitemaps.tests.https import *
  • new file django/contrib/sitemaps/tests/https.py

    diff --git a/django/contrib/sitemaps/tests/https.py b/django/contrib/sitemaps/tests/https.py
    new file mode 100644
    index 0000000..4646215
    - +  
     1import os
     2from datetime import date
     3from django.conf import settings
     4from django.contrib.auth.models import User
     5from django.contrib.sitemaps import Sitemap, GenericSitemap
     6from django.contrib.sites.models import Site
     7from django.core.exceptions import ImproperlyConfigured
     8from django.test import TestCase
     9from django.utils.unittest import skipUnless
     10from django.utils.formats import localize
     11from django.utils.translation import activate, deactivate
     12
     13
     14class HTTPSSitemapTests(TestCase):
     15    urls = 'django.contrib.sitemaps.tests.urls_https'
     16
     17    def setUp(self):
     18        if Site._meta.installed:
     19            self.base_url = 'https://example.com'
     20        else:
     21            self.base_url = 'https://testserver'
     22        self.old_USE_L10N = settings.USE_L10N
     23        self.old_Site_meta_installed = Site._meta.installed
     24        self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS
     25        self.old_Site_meta_installed = Site._meta.installed
     26        settings.TEMPLATE_DIRS = (
     27            os.path.join(os.path.dirname(__file__), 'templates'),
     28        )
     29        # Create a user that will double as sitemap content
     30        User.objects.create_user('testuser', 'test@example.com', 's3krit')
     31
     32    def tearDown(self):
     33        settings.USE_L10N = self.old_USE_L10N
     34        Site._meta.installed = self.old_Site_meta_installed
     35        settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS
     36        Site._meta.installed = self.old_Site_meta_installed
     37
     38    def test_simple_sitemap_index(self):
     39        "A simple sitemap index can be rendered"
     40        # Retrieve the sitemap.
     41        response = self.client.get('/simple/index.xml')
     42        # Check for all the important bits:
     43        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     44<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     45<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
     46</sitemapindex>
     47""" % self.base_url)
     48
     49    def test_simple_sitemap_custom_index(self):
     50        "A simple sitemap index can be rendered with a custom template"
     51        # Retrieve the sitemap.
     52        response = self.client.get('/simple/custom-index.xml')
     53        # Check for all the important bits:
     54        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     55<!-- This is a customised template -->
     56<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     57<sitemap><loc>%s/simple/sitemap-simple.xml</loc></sitemap>
     58</sitemapindex>
     59""" % self.base_url)
     60
     61    def test_simple_sitemap(self):
     62        "A simple sitemap can be rendered"
     63        # Retrieve the sitemap.
     64        response = self.client.get('/simple/sitemap.xml')
     65        # Check for all the important bits:
     66        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     67<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     68<url><loc>%s/location/</loc><lastmod>%s</lastmod><changefreq>never</changefreq><priority>0.5</priority></url>
     69</urlset>
     70""" % (self.base_url, date.today().strftime('%Y-%m-%d')))
     71
     72    def test_simple_custom_sitemap(self):
     73        "A simple sitemap can be rendered with a custom template"
     74        # Retrieve the sitemap.
     75        response = self.client.get('/simple/custom-sitemap.xml')
     76        # Check for all the important bits:
     77        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     78<!-- This is a customised template -->
     79<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     80<url><loc>%s/location/</loc><lastmod>%s</lastmod><changefreq>never</changefreq><priority>0.5</priority></url>
     81</urlset>
     82""" % (self.base_url, date.today().strftime('%Y-%m-%d')))
     83
     84    @skipUnless(settings.USE_I18N, "Internationalization is not enabled")
     85    def test_localized_priority(self):
     86        "The priority value should not be localized (Refs #14164)"
     87        # Localization should be active
     88        settings.USE_L10N = True
     89        activate('fr')
     90        self.assertEqual(u'0,3', localize(0.3))
     91
     92        # Retrieve the sitemap. Check that priorities
     93        # haven't been rendered in localized format
     94        response = self.client.get('/simple/sitemap.xml')
     95        self.assertContains(response, '<priority>0.5</priority>')
     96        self.assertContains(response, '<lastmod>%s</lastmod>' % date.today().strftime('%Y-%m-%d'))
     97        deactivate()
     98
     99    def test_generic_sitemap(self):
     100        "A minimal generic sitemap can be rendered"
     101        # Retrieve the sitemap.
     102        response = self.client.get('/generic/sitemap.xml')
     103
     104        expected = ''
     105        for username in User.objects.values_list("username", flat=True):
     106            expected += "<url><loc>%s/users/%s/</loc></url>" % (self.base_url, username)
     107        # Check for all the important bits:
     108        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     109<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     110%s
     111</urlset>
     112""" % expected)
     113
     114    @skipUnless("django.contrib.flatpages" in settings.INSTALLED_APPS, "django.contrib.flatpages app not installed.")
     115    def test_flatpage_sitemap(self):
     116        "Basic FlatPage sitemap test"
     117
     118        # Import FlatPage inside the test so that when django.contrib.flatpages
     119        # is not installed we don't get problems trying to delete Site
     120        # objects (FlatPage has an M2M to Site, Site.delete() tries to
     121        # delete related objects, but the M2M table doesn't exist.
     122        from django.contrib.flatpages.models import FlatPage
     123
     124        public = FlatPage.objects.create(
     125            url=u'/public/',
     126            title=u'Public Page',
     127            enable_comments=True,
     128            registration_required=False,
     129        )
     130        public.sites.add(settings.SITE_ID)
     131        private = FlatPage.objects.create(
     132            url=u'/private/',
     133            title=u'Private Page',
     134            enable_comments=True,
     135            registration_required=True
     136        )
     137        private.sites.add(settings.SITE_ID)
     138        response = self.client.get('/flatpages/sitemap.xml')
     139        # Public flatpage should be in the sitemap
     140        self.assertContains(response, '<loc>%s%s</loc>' % (self.base_url, public.url))
     141        # Private flatpage should not be in the sitemap
     142        self.assertNotContains(response, '<loc>%s%s</loc>' % (self.base_url, private.url))
     143
     144    def test_requestsite_sitemap(self):
     145        # Make sure hitting the flatpages sitemap without the sites framework
     146        # installed doesn't raise an exception
     147        Site._meta.installed = False
     148        # Retrieve the sitemap.
     149        response = self.client.get('/simple/sitemap.xml')
     150        # Check for all the important bits:
     151        self.assertEqual(response.content, """<?xml version="1.0" encoding="UTF-8"?>
     152<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     153<url><loc>https://testserver/location/</loc><lastmod>%s</lastmod><changefreq>never</changefreq><priority>0.5</priority></url>
     154</urlset>
     155""" % date.today().strftime('%Y-%m-%d'))
     156
     157    @skipUnless("django.contrib.sites" in settings.INSTALLED_APPS, "django.contrib.sites app not installed.")
     158    def test_sitemap_get_urls_no_site_1(self):
     159        """
     160        Check we get ImproperlyConfigured if we don't pass a site object to
     161        Sitemap.get_urls and no Site objects exist
     162        """
     163        Site.objects.all().delete()
     164        self.assertRaises(ImproperlyConfigured, Sitemap().get_urls)
     165
     166    def test_sitemap_get_urls_no_site_2(self):
     167        """
     168        Check we get ImproperlyConfigured when we don't pass a site object to
     169        Sitemap.get_urls if Site objects exists, but the sites framework is not
     170        actually installed.
     171        """
     172        Site._meta.installed = False
     173        self.assertRaises(ImproperlyConfigured, Sitemap().get_urls)
     174
     175    def test_sitemap_item(self):
     176        """
     177        Check to make sure that the raw item is included with each
     178        Sitemap.get_url() url result.
     179        """
     180        user_sitemap = GenericSitemap({'queryset': User.objects.all()})
     181        def is_user(url):
     182            return isinstance(url['item'], User)
     183        item_in_url_info = all(map(is_user, user_sitemap.get_urls()))
     184        self.assertTrue(item_in_url_info)
  • new file django/contrib/sitemaps/tests/urls_https.py

    diff --git a/django/contrib/sitemaps/tests/urls_https.py b/django/contrib/sitemaps/tests/urls_https.py
    new file mode 100644
    index 0000000..7ff0a1d
    - +  
     1from datetime import datetime
     2from django.conf.urls.defaults import *
     3from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap
     4from django.contrib.auth.models import User
     5
     6class HTTPSSimpleSitemap(Sitemap):
     7    changefreq = "never"
     8    priority = 0.5
     9    location = '/location/'
     10    lastmod = datetime.now()
     11    protocol = 'https'
     12
     13    def items(self):
     14        return [object()]
     15
     16class HTTPSGenericSitemap(GenericSitemap):
     17    protocol = 'https'
     18
     19class HTTPSFlatPageSitemap(FlatPageSitemap):
     20    protocol = 'https'
     21
     22simple_sitemaps = {
     23    'simple': HTTPSSimpleSitemap,
     24}
     25
     26generic_sitemaps = {
     27    'generic': HTTPSGenericSitemap({
     28        'queryset': User.objects.all()
     29    }),
     30}
     31
     32flatpage_sitemaps = {
     33    'flatpages': HTTPSFlatPageSitemap,
     34}
     35
     36urlpatterns = patterns('django.contrib.sitemaps.views',
     37    (r'^simple/index\.xml$', 'index', {'sitemaps': simple_sitemaps}),
     38    (r'^simple/custom-index\.xml$', 'index', {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap_index.xml'}),
     39    (r'^simple/sitemap-(?P<section>.+)\.xml$', 'sitemap', {'sitemaps': simple_sitemaps}),
     40    (r'^simple/sitemap\.xml$', 'sitemap', {'sitemaps': simple_sitemaps}),
     41    (r'^simple/custom-sitemap\.xml$', 'sitemap', {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
     42    (r'^generic/sitemap\.xml$', 'sitemap', {'sitemaps': generic_sitemaps}),
     43    (r'^flatpages/sitemap\.xml$', 'sitemap', {'sitemaps': flatpage_sitemaps}),
     44)
  • django/contrib/sitemaps/views.py

    diff --git a/django/contrib/sitemaps/views.py b/django/contrib/sitemaps/views.py
    index b117b33..7dcb303 100644
    a b def index(request, sitemaps,  
    1010        template_name='sitemap_index.xml', mimetype='application/xml'):
    1111    current_site = get_current_site(request)
    1212    sites = []
    13     protocol = request.is_secure() and 'https' or 'http'
    1413    for section, site in sitemaps.items():
    1514        site.request = request
    1615        if callable(site):
    def index(request, sitemaps,  
    1817        else:
    1918            pages = site.paginator.num_pages
    2019        sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap', kwargs={'section': section})
    21         sites.append('%s://%s%s' % (protocol, current_site.domain, sitemap_url))
     20        sites.append('%s://%s%s' % (site.protocol, current_site.domain, sitemap_url))
    2221        if pages > 1:
    2322            for page in range(2, pages+1):
    24                 sites.append('%s://%s%s?p=%s' % (protocol, current_site.domain, sitemap_url, page))
     23                sites.append('%s://%s%s?p=%s' % (site.protocol, current_site.domain, sitemap_url, page))
    2524    return TemplateResponse(request, template_name, {'sitemaps': sites}, mimetype=mimetype)
    2625
    2726def sitemap(request, sitemaps, section=None,
    def sitemap(request, sitemaps, section=None,  
    4443            raise Http404("Page %s empty" % page)
    4544        except PageNotAnInteger:
    4645            raise Http404("No page '%s'" % page)
    47     return TemplateResponse(request, template_name, {'urlset': urls}, mimetype=mimetype)
    48  No newline at end of file
     46    return TemplateResponse(request, template_name, {'urlset': urls}, mimetype=mimetype)
Back to Top