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 năm trước cách đây
mục cha
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`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^