Browse Source

Fixed #22782 -- Added i18n attr to Sitemap class

It makes possible to have your sitemap in multiple languages when
using i18n in URLs.
Luan Pablo 10 years ago
parent
commit
407d070329

+ 1 - 0
AUTHORS

@@ -484,6 +484,7 @@ answer newbie questions, and generally made Django that much better:
     Christian Oudard <christian.oudard@gmail.com>
     oggie rob <oz.robharvey@gmail.com>
     oggy <ognjen.maric@gmail.com>
+    Luan Pablo <luanpab@gmail.com>
     Tomek Paczkowski <tomek@hauru.eu>
     Jens Page
     Guillaume Pannatier <guillaume.pannatier@gmail.com>

+ 15 - 0
django/contrib/sitemaps/__init__.py

@@ -1,6 +1,8 @@
 from django.apps import apps as django_apps
+from django.conf import settings
 from django.core import urlresolvers, paginator
 from django.core.exceptions import ImproperlyConfigured
+from django.utils import translation
 from django.utils.six.moves.urllib.parse import urlencode
 from django.utils.six.moves.urllib.request import urlopen
 
@@ -89,6 +91,19 @@ class Sitemap(object):
                 raise ImproperlyConfigured("To use sitemaps, either enable the sites framework or pass a Site/RequestSite object in your view.")
         domain = site.domain
 
+        if getattr(self, 'i18n', False):
+            urls = []
+            current_lang_code = translation.get_language()
+            for lang_code, lang_name in settings.LANGUAGES:
+                translation.activate(lang_code)
+                urls += self._urls(page, protocol, domain)
+            translation.activate(current_lang_code)
+        else:
+            urls = self._urls(page, protocol, domain)
+
+        return urls
+
+    def _urls(self, page, protocol, domain):
         urls = []
         latest_lastmod = None
         all_items_lastmod = True  # track if all items have a lastmod

+ 12 - 0
django/contrib/sitemaps/tests/base.py

@@ -1,5 +1,6 @@
 from django.apps import apps
 from django.core.cache import cache
+from django.core.urlresolvers import reverse
 from django.db import models
 from django.test import TestCase, override_settings
 
@@ -17,6 +18,16 @@ class TestModel(models.Model):
         return '/testmodel/%s/' % self.id
 
 
+class I18nTestModel(models.Model):
+    name = models.CharField(max_length=100)
+
+    class Meta:
+        app_label = 'sitemaps'
+
+    def get_absolute_url(self):
+        return reverse('i18n_testmodel', args=[self.id])
+
+
 @override_settings(ROOT_URLCONF='django.contrib.sitemaps.tests.urls.http')
 class SitemapTestsBase(TestCase):
     protocol = 'http'
@@ -28,3 +39,4 @@ class SitemapTestsBase(TestCase):
         cache.clear()
         # Create an object for sitemap content.
         TestModel.objects.create(name='Test Object')
+        I18nTestModel.objects.create(name='Test Object')

+ 11 - 0
django/contrib/sitemaps/tests/test_http.py

@@ -171,3 +171,14 @@ class HTTPSitemapTests(SitemapTestsBase):
     def test_empty_sitemap(self):
         response = self.client.get('/empty/sitemap.xml')
         self.assertEqual(response.status_code, 200)
+
+    @override_settings(LANGUAGES=(('en', 'English'), ('pt', 'Portuguese')))
+    def test_simple_i18nsitemap_index(self):
+        "A simple i18n sitemap index can be rendered"
+        response = self.client.get('/simple/i18n.xml')
+        expected_content = """<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+<url><loc>{0}/en/i18n/testmodel/1/</loc><changefreq>never</changefreq><priority>0.5</priority></url><url><loc>{0}/pt/i18n/testmodel/1/</loc><changefreq>never</changefreq><priority>0.5</priority></url>
+</urlset>
+""".format(self.base_url)
+        self.assertXMLEqual(response.content.decode('utf-8'), expected_content)

+ 25 - 1
django/contrib/sitemaps/tests/urls/http.py

@@ -1,9 +1,11 @@
 from datetime import datetime
 from django.conf.urls import url
+from django.conf.urls.i18n import i18n_patterns
 from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views
+from django.http import HttpResponse
 from django.views.decorators.cache import cache_page
 
-from django.contrib.sitemaps.tests.base import TestModel
+from django.contrib.sitemaps.tests.base import I18nTestModel, TestModel
 
 
 class SimpleSitemap(Sitemap):
@@ -16,6 +18,15 @@ class SimpleSitemap(Sitemap):
         return [object()]
 
 
+class SimpleI18nSitemap(Sitemap):
+    changefreq = "never"
+    priority = 0.5
+    i18n = True
+
+    def items(self):
+        return I18nTestModel.objects.all()
+
+
 class EmptySitemap(Sitemap):
     changefreq = "never"
     priority = 0.5
@@ -42,10 +53,18 @@ class FixedLastmodMixedSitemap(Sitemap):
         return [o1, o2]
 
 
+def testmodelview(request, id):
+    return HttpResponse()
+
+
 simple_sitemaps = {
     'simple': SimpleSitemap,
 }
 
+simple_i18nsitemaps = {
+    'simple': SimpleI18nSitemap,
+}
+
 empty_sitemaps = {
     'empty': EmptySitemap,
 }
@@ -74,6 +93,7 @@ urlpatterns = [
     url(r'^simple/sitemap-(?P<section>.+)\.xml$', views.sitemap,
         {'sitemaps': simple_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
     url(r'^simple/sitemap\.xml$', views.sitemap, {'sitemaps': simple_sitemaps}),
+    url(r'^simple/i18n\.xml$', views.sitemap, {'sitemaps': simple_i18nsitemaps}),
     url(r'^simple/custom-sitemap\.xml$', views.sitemap,
         {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
     url(r'^empty/sitemap\.xml$', views.sitemap, {'sitemaps': empty_sitemaps}),
@@ -86,3 +106,7 @@ urlpatterns = [
     url(r'^cached/sitemap-(?P<section>.+)\.xml', cache_page(1)(views.sitemap),
         {'sitemaps': simple_sitemaps}, name='cached_sitemap')
 ]
+
+urlpatterns += i18n_patterns(
+    url(r'^i18n/testmodel/(?P<id>\d+)/$', testmodelview, name='i18n_testmodel'),
+)

+ 9 - 0
docs/ref/contrib/sitemaps.txt

@@ -232,6 +232,15 @@ Sitemap class reference
         sitemap was requested is used. If the sitemap is built outside the
         context of a request, the default is ``'http'``.
 
+    .. attribute:: Sitemap.i18n
+
+        .. versionadded:: 1.8
+
+        **Optional.**
+
+        A boolean attribute that defines if the URLs of this sitemap should
+        be generated using all of your :setting:`LANGUAGES`. The default is
+        ``False``.
 
 Shortcuts
 =========

+ 2 - 1
docs/releases/1.8.txt

@@ -83,7 +83,8 @@ Minor features
 :mod:`django.contrib.sitemaps`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-* ...
+* The new :attr:`Sitemap.i18n <django.contrib.sitemaps.Sitemap.i18n>` attribute
+  allows you to generate a sitemap based on the :setting:`LANGUAGES` setting.
 
 :mod:`django.contrib.sites`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^