Fixed #22782 -- Added i18n attr to Sitemap class
It makes possible to have your sitemap in multiple languages when using i18n in URLs.
This commit is contained in:
parent
78c32f1caa
commit
407d070329
1
AUTHORS
1
AUTHORS
|
@ -484,6 +484,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Christian Oudard <christian.oudard@gmail.com>
|
Christian Oudard <christian.oudard@gmail.com>
|
||||||
oggie rob <oz.robharvey@gmail.com>
|
oggie rob <oz.robharvey@gmail.com>
|
||||||
oggy <ognjen.maric@gmail.com>
|
oggy <ognjen.maric@gmail.com>
|
||||||
|
Luan Pablo <luanpab@gmail.com>
|
||||||
Tomek Paczkowski <tomek@hauru.eu>
|
Tomek Paczkowski <tomek@hauru.eu>
|
||||||
Jens Page
|
Jens Page
|
||||||
Guillaume Pannatier <guillaume.pannatier@gmail.com>
|
Guillaume Pannatier <guillaume.pannatier@gmail.com>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from django.apps import apps as django_apps
|
from django.apps import apps as django_apps
|
||||||
|
from django.conf import settings
|
||||||
from django.core import urlresolvers, paginator
|
from django.core import urlresolvers, paginator
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
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.parse import urlencode
|
||||||
from django.utils.six.moves.urllib.request import urlopen
|
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.")
|
raise ImproperlyConfigured("To use sitemaps, either enable the sites framework or pass a Site/RequestSite object in your view.")
|
||||||
domain = site.domain
|
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 = []
|
urls = []
|
||||||
latest_lastmod = None
|
latest_lastmod = None
|
||||||
all_items_lastmod = True # track if all items have a lastmod
|
all_items_lastmod = True # track if all items have a lastmod
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
@ -17,6 +18,16 @@ class TestModel(models.Model):
|
||||||
return '/testmodel/%s/' % self.id
|
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')
|
@override_settings(ROOT_URLCONF='django.contrib.sitemaps.tests.urls.http')
|
||||||
class SitemapTestsBase(TestCase):
|
class SitemapTestsBase(TestCase):
|
||||||
protocol = 'http'
|
protocol = 'http'
|
||||||
|
@ -28,3 +39,4 @@ class SitemapTestsBase(TestCase):
|
||||||
cache.clear()
|
cache.clear()
|
||||||
# Create an object for sitemap content.
|
# Create an object for sitemap content.
|
||||||
TestModel.objects.create(name='Test Object')
|
TestModel.objects.create(name='Test Object')
|
||||||
|
I18nTestModel.objects.create(name='Test Object')
|
||||||
|
|
|
@ -171,3 +171,14 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||||
def test_empty_sitemap(self):
|
def test_empty_sitemap(self):
|
||||||
response = self.client.get('/empty/sitemap.xml')
|
response = self.client.get('/empty/sitemap.xml')
|
||||||
self.assertEqual(response.status_code, 200)
|
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)
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from django.conf.urls import url
|
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.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views
|
||||||
|
from django.http import HttpResponse
|
||||||
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 I18nTestModel, TestModel
|
||||||
|
|
||||||
|
|
||||||
class SimpleSitemap(Sitemap):
|
class SimpleSitemap(Sitemap):
|
||||||
|
@ -16,6 +18,15 @@ class SimpleSitemap(Sitemap):
|
||||||
return [object()]
|
return [object()]
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleI18nSitemap(Sitemap):
|
||||||
|
changefreq = "never"
|
||||||
|
priority = 0.5
|
||||||
|
i18n = True
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
return I18nTestModel.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class EmptySitemap(Sitemap):
|
class EmptySitemap(Sitemap):
|
||||||
changefreq = "never"
|
changefreq = "never"
|
||||||
priority = 0.5
|
priority = 0.5
|
||||||
|
@ -42,10 +53,18 @@ class FixedLastmodMixedSitemap(Sitemap):
|
||||||
return [o1, o2]
|
return [o1, o2]
|
||||||
|
|
||||||
|
|
||||||
|
def testmodelview(request, id):
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
|
||||||
simple_sitemaps = {
|
simple_sitemaps = {
|
||||||
'simple': SimpleSitemap,
|
'simple': SimpleSitemap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simple_i18nsitemaps = {
|
||||||
|
'simple': SimpleI18nSitemap,
|
||||||
|
}
|
||||||
|
|
||||||
empty_sitemaps = {
|
empty_sitemaps = {
|
||||||
'empty': EmptySitemap,
|
'empty': EmptySitemap,
|
||||||
}
|
}
|
||||||
|
@ -74,6 +93,7 @@ urlpatterns = [
|
||||||
url(r'^simple/sitemap-(?P<section>.+)\.xml$', views.sitemap,
|
url(r'^simple/sitemap-(?P<section>.+)\.xml$', views.sitemap,
|
||||||
{'sitemaps': simple_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
|
{'sitemaps': simple_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
|
||||||
url(r'^simple/sitemap\.xml$', views.sitemap, {'sitemaps': simple_sitemaps}),
|
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,
|
url(r'^simple/custom-sitemap\.xml$', views.sitemap,
|
||||||
{'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
|
{'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
|
||||||
url(r'^empty/sitemap\.xml$', views.sitemap, {'sitemaps': empty_sitemaps}),
|
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),
|
url(r'^cached/sitemap-(?P<section>.+)\.xml', cache_page(1)(views.sitemap),
|
||||||
{'sitemaps': simple_sitemaps}, name='cached_sitemap')
|
{'sitemaps': simple_sitemaps}, name='cached_sitemap')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
urlpatterns += i18n_patterns(
|
||||||
|
url(r'^i18n/testmodel/(?P<id>\d+)/$', testmodelview, name='i18n_testmodel'),
|
||||||
|
)
|
||||||
|
|
|
@ -232,6 +232,15 @@ Sitemap class reference
|
||||||
sitemap was requested is used. If the sitemap is built outside the
|
sitemap was requested is used. If the sitemap is built outside the
|
||||||
context of a request, the default is ``'http'``.
|
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
|
Shortcuts
|
||||||
=========
|
=========
|
||||||
|
|
|
@ -83,7 +83,8 @@ Minor features
|
||||||
:mod:`django.contrib.sitemaps`
|
: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`
|
:mod:`django.contrib.sites`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
Loading…
Reference in New Issue