1. =====================
    
  2. The sitemap framework
    
  3. =====================
    
  4. 
    
  5. .. module:: django.contrib.sitemaps
    
  6.    :synopsis: A framework for generating Google sitemap XML files.
    
  7. 
    
  8. Django comes with a high-level sitemap-generating framework to create sitemap_
    
  9. XML files.
    
  10. 
    
  11. .. _sitemap: https://www.sitemaps.org/
    
  12. 
    
  13. Overview
    
  14. ========
    
  15. 
    
  16. A sitemap is an XML file on your website that tells search-engine indexers how
    
  17. frequently your pages change and how "important" certain pages are in relation
    
  18. to other pages on your site. This information helps search engines index your
    
  19. site.
    
  20. 
    
  21. The Django sitemap framework automates the creation of this XML file by letting
    
  22. you express this information in Python code.
    
  23. 
    
  24. It works much like Django's :doc:`syndication framework
    
  25. </ref/contrib/syndication>`. To create a sitemap, write a
    
  26. :class:`~django.contrib.sitemaps.Sitemap` class and point to it in your
    
  27. :doc:`URLconf </topics/http/urls>`.
    
  28. 
    
  29. Installation
    
  30. ============
    
  31. 
    
  32. To install the sitemap app, follow these steps:
    
  33. 
    
  34. #. Add ``'django.contrib.sitemaps'`` to your :setting:`INSTALLED_APPS` setting.
    
  35. 
    
  36. #. Make sure your :setting:`TEMPLATES` setting contains a ``DjangoTemplates``
    
  37.    backend whose ``APP_DIRS`` options is set to ``True``. It's in there by
    
  38.    default, so you'll only need to change this if you've changed that setting.
    
  39. 
    
  40. #. Make sure you've installed the :mod:`sites framework<django.contrib.sites>`.
    
  41. 
    
  42. (Note: The sitemap application doesn't install any database tables. The only
    
  43. reason it needs to go into :setting:`INSTALLED_APPS` is so that the
    
  44. :func:`~django.template.loaders.app_directories.Loader` template
    
  45. loader can find the default templates.)
    
  46. 
    
  47. Initialization
    
  48. ==============
    
  49. 
    
  50. .. function:: views.sitemap(request, sitemaps, section=None, template_name='sitemap.xml', content_type='application/xml')
    
  51. 
    
  52. To activate sitemap generation on your Django site, add this line to your
    
  53. :doc:`URLconf </topics/http/urls>`::
    
  54. 
    
  55.     from django.contrib.sitemaps.views import sitemap
    
  56. 
    
  57.     path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
    
  58.          name='django.contrib.sitemaps.views.sitemap')
    
  59. 
    
  60. This tells Django to build a sitemap when a client accesses :file:`/sitemap.xml`.
    
  61. 
    
  62. The name of the sitemap file is not important, but the location is. Search
    
  63. engines will only index links in your sitemap for the current URL level and
    
  64. below. For instance, if :file:`sitemap.xml` lives in your root directory, it may
    
  65. reference any URL in your site. However, if your sitemap lives at
    
  66. :file:`/content/sitemap.xml`, it may only reference URLs that begin with
    
  67. :file:`/content/`.
    
  68. 
    
  69. The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``.
    
  70. ``sitemaps`` should be a dictionary that maps a short section label (e.g.,
    
  71. ``blog`` or ``news``) to its :class:`~django.contrib.sitemaps.Sitemap` class
    
  72. (e.g., ``BlogSitemap`` or ``NewsSitemap``). It may also map to an *instance* of
    
  73. a :class:`~django.contrib.sitemaps.Sitemap` class (e.g.,
    
  74. ``BlogSitemap(some_var)``).
    
  75. 
    
  76. ``Sitemap`` classes
    
  77. ===================
    
  78. 
    
  79. A :class:`~django.contrib.sitemaps.Sitemap` class is a Python class that
    
  80. represents a "section" of entries in your sitemap. For example, one
    
  81. :class:`~django.contrib.sitemaps.Sitemap` class could represent all the entries
    
  82. of your blog, while another could represent all of the events in your events
    
  83. calendar.
    
  84. 
    
  85. In the simplest case, all these sections get lumped together into one
    
  86. :file:`sitemap.xml`, but it's also possible to use the framework to generate a
    
  87. sitemap index that references individual sitemap files, one per section. (See
    
  88. `Creating a sitemap index`_ below.)
    
  89. 
    
  90. :class:`~django.contrib.sitemaps.Sitemap` classes must subclass
    
  91. ``django.contrib.sitemaps.Sitemap``. They can live anywhere in your codebase.
    
  92. 
    
  93. An example
    
  94. ==========
    
  95. 
    
  96. Let's assume you have a blog system, with an ``Entry`` model, and you want your
    
  97. sitemap to include all the links to your individual blog entries. Here's how
    
  98. your sitemap class might look::
    
  99. 
    
  100.     from django.contrib.sitemaps import Sitemap
    
  101.     from blog.models import Entry
    
  102. 
    
  103.     class BlogSitemap(Sitemap):
    
  104.         changefreq = "never"
    
  105.         priority = 0.5
    
  106. 
    
  107.         def items(self):
    
  108.             return Entry.objects.filter(is_draft=False)
    
  109. 
    
  110.         def lastmod(self, obj):
    
  111.             return obj.pub_date
    
  112. 
    
  113. Note:
    
  114. 
    
  115. * :attr:`~Sitemap.changefreq` and :attr:`~Sitemap.priority` are class
    
  116.   attributes corresponding to ``<changefreq>`` and ``<priority>`` elements,
    
  117.   respectively. They can be made callable as functions, as
    
  118.   :attr:`~Sitemap.lastmod` was in the example.
    
  119. * :attr:`~Sitemap.items()` is a method that returns a :term:`sequence` or
    
  120.   ``QuerySet`` of objects. The objects returned will get passed to any callable
    
  121.   methods corresponding to a sitemap property (:attr:`~Sitemap.location`,
    
  122.   :attr:`~Sitemap.lastmod`, :attr:`~Sitemap.changefreq`, and
    
  123.   :attr:`~Sitemap.priority`).
    
  124. * :attr:`~Sitemap.lastmod` should return a :class:`~datetime.datetime`.
    
  125. * There is no :attr:`~Sitemap.location` method in this example, but you
    
  126.   can provide it in order to specify the URL for your object. By default,
    
  127.   :attr:`~Sitemap.location()` calls ``get_absolute_url()`` on each object
    
  128.   and returns the result.
    
  129. 
    
  130. ``Sitemap`` class reference
    
  131. ===========================
    
  132. 
    
  133. .. class:: Sitemap
    
  134. 
    
  135.     A ``Sitemap`` class can define the following methods/attributes:
    
  136. 
    
  137.     .. attribute:: Sitemap.items
    
  138. 
    
  139.         **Required.** A method that returns a :term:`sequence` or ``QuerySet``
    
  140.         of objects. The framework doesn't care what *type* of objects they are;
    
  141.         all that matters is that these objects get passed to the
    
  142.         :attr:`~Sitemap.location()`, :attr:`~Sitemap.lastmod()`,
    
  143.         :attr:`~Sitemap.changefreq()` and :attr:`~Sitemap.priority()` methods.
    
  144. 
    
  145.     .. attribute:: Sitemap.location
    
  146. 
    
  147.         **Optional.** Either a method or attribute.
    
  148. 
    
  149.         If it's a method, it should return the absolute path for a given object
    
  150.         as returned by :attr:`~Sitemap.items()`.
    
  151. 
    
  152.         If it's an attribute, its value should be a string representing an
    
  153.         absolute path to use for *every* object returned by
    
  154.         :attr:`~Sitemap.items()`.
    
  155. 
    
  156.         In both cases, "absolute path" means a URL that doesn't include the
    
  157.         protocol or domain. Examples:
    
  158. 
    
  159.         * Good: :file:`'/foo/bar/'`
    
  160.         * Bad: :file:`'example.com/foo/bar/'`
    
  161.         * Bad: :file:`'https://example.com/foo/bar/'`
    
  162. 
    
  163.         If :attr:`~Sitemap.location` isn't provided, the framework will call
    
  164.         the ``get_absolute_url()`` method on each object as returned by
    
  165.         :attr:`~Sitemap.items()`.
    
  166. 
    
  167.         To specify a protocol other than ``'http'``, use
    
  168.         :attr:`~Sitemap.protocol`.
    
  169. 
    
  170.     .. attribute:: Sitemap.lastmod
    
  171. 
    
  172.         **Optional.** Either a method or attribute.
    
  173. 
    
  174.         If it's a method, it should take one argument -- an object as returned
    
  175.         by :attr:`~Sitemap.items()` -- and return that object's last-modified
    
  176.         date/time as a :class:`~datetime.datetime`.
    
  177. 
    
  178.         If it's an attribute, its value should be a :class:`~datetime.datetime`
    
  179.         representing the last-modified date/time for *every* object returned by
    
  180.         :attr:`~Sitemap.items()`.
    
  181. 
    
  182.         If all items in a sitemap have a :attr:`~Sitemap.lastmod`, the sitemap
    
  183.         generated by :func:`views.sitemap` will have a ``Last-Modified``
    
  184.         header equal to the latest ``lastmod``. You can activate the
    
  185.         :class:`~django.middleware.http.ConditionalGetMiddleware` to make
    
  186.         Django respond appropriately to requests with an ``If-Modified-Since``
    
  187.         header which will prevent sending the sitemap if it hasn't changed.
    
  188. 
    
  189.     .. attribute:: Sitemap.paginator
    
  190. 
    
  191.         **Optional.**
    
  192. 
    
  193.         This property returns a :class:`~django.core.paginator.Paginator` for
    
  194.         :attr:`~Sitemap.items()`. If you generate sitemaps in a batch you may
    
  195.         want to override this as a cached property in order to avoid multiple
    
  196.         ``items()`` calls.
    
  197. 
    
  198.     .. attribute:: Sitemap.changefreq
    
  199. 
    
  200.         **Optional.** Either a method or attribute.
    
  201. 
    
  202.         If it's a method, it should take one argument -- an object as returned
    
  203.         by :attr:`~Sitemap.items()` -- and return that object's change
    
  204.         frequency as a string.
    
  205. 
    
  206.         If it's an attribute, its value should be a string representing the
    
  207.         change frequency of *every* object returned by :attr:`~Sitemap.items()`.
    
  208. 
    
  209.         Possible values for :attr:`~Sitemap.changefreq`, whether you use a
    
  210.         method or attribute, are:
    
  211. 
    
  212.         * ``'always'``
    
  213.         * ``'hourly'``
    
  214.         * ``'daily'``
    
  215.         * ``'weekly'``
    
  216.         * ``'monthly'``
    
  217.         * ``'yearly'``
    
  218.         * ``'never'``
    
  219. 
    
  220.     .. attribute:: Sitemap.priority
    
  221. 
    
  222.         **Optional.** Either a method or attribute.
    
  223. 
    
  224.         If it's a method, it should take one argument -- an object as returned
    
  225.         by :attr:`~Sitemap.items()` -- and return that object's priority as
    
  226.         either a string or float.
    
  227. 
    
  228.         If it's an attribute, its value should be either a string or float
    
  229.         representing the priority of *every* object returned by
    
  230.         :attr:`~Sitemap.items()`.
    
  231. 
    
  232.         Example values for :attr:`~Sitemap.priority`: ``0.4``, ``1.0``. The
    
  233.         default priority of a page is ``0.5``. See the `sitemaps.org
    
  234.         documentation`_ for more.
    
  235. 
    
  236.         .. _sitemaps.org documentation: https://www.sitemaps.org/protocol.html#prioritydef
    
  237. 
    
  238.     .. attribute:: Sitemap.protocol
    
  239. 
    
  240.         **Optional.**
    
  241. 
    
  242.         This attribute defines the protocol (``'http'`` or ``'https'``) of the
    
  243.         URLs in the sitemap. If it isn't set, the protocol with which the
    
  244.         sitemap was requested is used. If the sitemap is built outside the
    
  245.         context of a request, the default is ``'http'``.
    
  246. 
    
  247.         .. deprecated:: 4.0
    
  248. 
    
  249.             The default protocol for sitemaps built outside the context of a
    
  250.             request will change from ``'http'`` to ``'https'`` in Django 5.0.
    
  251. 
    
  252.     .. attribute:: Sitemap.limit
    
  253. 
    
  254.         **Optional.**
    
  255. 
    
  256.         This attribute defines the maximum number of URLs included on each page
    
  257.         of the sitemap. Its value should not exceed the default value of
    
  258.         ``50000``, which is the upper limit allowed in the `Sitemaps protocol
    
  259.         <https://www.sitemaps.org/protocol.html#index>`_.
    
  260. 
    
  261.     .. attribute:: Sitemap.i18n
    
  262. 
    
  263.         **Optional.**
    
  264. 
    
  265.         A boolean attribute that defines if the URLs of this sitemap should
    
  266.         be generated using all of your :setting:`LANGUAGES`. The default is
    
  267.         ``False``.
    
  268. 
    
  269.     .. attribute:: Sitemap.languages
    
  270. 
    
  271.         **Optional.**
    
  272. 
    
  273.         A :term:`sequence` of :term:`language codes<language code>` to use for
    
  274.         generating alternate links when :attr:`~Sitemap.i18n` is enabled.
    
  275.         Defaults to :setting:`LANGUAGES`.
    
  276. 
    
  277.     .. attribute:: Sitemap.alternates
    
  278. 
    
  279.         **Optional.**
    
  280. 
    
  281.         A boolean attribute. When used in conjunction with
    
  282.         :attr:`~Sitemap.i18n` generated URLs will each have a list of alternate
    
  283.         links pointing to other language versions using the `hreflang
    
  284.         attribute`_. The default is ``False``.
    
  285. 
    
  286.         .. _hreflang attribute: https://developers.google.com/search/docs/advanced/crawling/localized-versions
    
  287. 
    
  288.     .. attribute:: Sitemap.x_default
    
  289. 
    
  290.         **Optional.**
    
  291. 
    
  292.         A boolean attribute. When ``True`` the alternate links generated by
    
  293.         :attr:`~Sitemap.alternates` will contain a ``hreflang="x-default"``
    
  294.         fallback entry with a value of :setting:`LANGUAGE_CODE`. The default is
    
  295.         ``False``.
    
  296. 
    
  297.     .. method:: Sitemap.get_latest_lastmod()
    
  298. 
    
  299.         .. versionadded:: 4.1
    
  300. 
    
  301.         **Optional.** A method that returns the latest value returned by
    
  302.         :attr:`~Sitemap.lastmod`. This function is used to add the ``lastmod``
    
  303.         attribute to :ref:`Sitemap index context
    
  304.         variables<sitemap-index-context-variables>`.
    
  305. 
    
  306.         By default :meth:`~Sitemap.get_latest_lastmod` returns:
    
  307. 
    
  308.         * If :attr:`~Sitemap.lastmod` is an attribute:
    
  309.           :attr:`~Sitemap.lastmod`.
    
  310.         * If :attr:`~Sitemap.lastmod` is a method:
    
  311.           The latest ``lastmod`` returned by calling the method with all
    
  312.           items returned by :meth:`Sitemap.items`.
    
  313. 
    
  314. Shortcuts
    
  315. =========
    
  316. 
    
  317. The sitemap framework provides a convenience class for a common case:
    
  318. 
    
  319. .. class:: GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)
    
  320. 
    
  321.     The :class:`django.contrib.sitemaps.GenericSitemap` class allows you to
    
  322.     create a sitemap by passing it a dictionary which has to contain at least
    
  323.     a ``queryset`` entry. This queryset will be used to generate the items
    
  324.     of the sitemap. It may also have a ``date_field`` entry that
    
  325.     specifies a date field for objects retrieved from the ``queryset``.
    
  326.     This will be used for the :attr:`~Sitemap.lastmod` attribute and
    
  327.     :meth:`~Sitemap.get_latest_lastmod` methods in the in the
    
  328.     generated sitemap.
    
  329. 
    
  330.     The :attr:`~Sitemap.priority`, :attr:`~Sitemap.changefreq`,
    
  331.     and :attr:`~Sitemap.protocol` keyword arguments allow specifying these
    
  332.     attributes for all URLs.
    
  333. 
    
  334. Example
    
  335. -------
    
  336. 
    
  337. Here's an example of a :doc:`URLconf </topics/http/urls>` using
    
  338. :class:`GenericSitemap`::
    
  339. 
    
  340.     from django.contrib.sitemaps import GenericSitemap
    
  341.     from django.contrib.sitemaps.views import sitemap
    
  342.     from django.urls import path
    
  343.     from blog.models import Entry
    
  344. 
    
  345.     info_dict = {
    
  346.         'queryset': Entry.objects.all(),
    
  347.         'date_field': 'pub_date',
    
  348.     }
    
  349. 
    
  350.     urlpatterns = [
    
  351.         # some generic view using info_dict
    
  352.         # ...
    
  353. 
    
  354.         # the sitemap
    
  355.         path('sitemap.xml', sitemap,
    
  356.              {'sitemaps': {'blog': GenericSitemap(info_dict, priority=0.6)}},
    
  357.              name='django.contrib.sitemaps.views.sitemap'),
    
  358.     ]
    
  359. 
    
  360. .. _URLconf: ../url_dispatch/
    
  361. 
    
  362. Sitemap for static views
    
  363. ========================
    
  364. 
    
  365. Often you want the search engine crawlers to index views which are neither
    
  366. object detail pages nor flatpages. The solution is to explicitly list URL
    
  367. names for these views in ``items`` and call :func:`~django.urls.reverse` in
    
  368. the ``location`` method of the sitemap. For example::
    
  369. 
    
  370.     # sitemaps.py
    
  371.     from django.contrib import sitemaps
    
  372.     from django.urls import reverse
    
  373. 
    
  374.     class StaticViewSitemap(sitemaps.Sitemap):
    
  375.         priority = 0.5
    
  376.         changefreq = 'daily'
    
  377. 
    
  378.         def items(self):
    
  379.             return ['main', 'about', 'license']
    
  380. 
    
  381.         def location(self, item):
    
  382.             return reverse(item)
    
  383. 
    
  384.     # urls.py
    
  385.     from django.contrib.sitemaps.views import sitemap
    
  386.     from django.urls import path
    
  387. 
    
  388.     from .sitemaps import StaticViewSitemap
    
  389.     from . import views
    
  390. 
    
  391.     sitemaps = {
    
  392.         'static': StaticViewSitemap,
    
  393.     }
    
  394. 
    
  395.     urlpatterns = [
    
  396.         path('', views.main, name='main'),
    
  397.         path('about/', views.about, name='about'),
    
  398.         path('license/', views.license, name='license'),
    
  399.         # ...
    
  400.         path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
    
  401.              name='django.contrib.sitemaps.views.sitemap')
    
  402.     ]
    
  403. 
    
  404. 
    
  405. Creating a sitemap index
    
  406. ========================
    
  407. 
    
  408. .. function:: views.index(request, sitemaps, template_name='sitemap_index.xml', content_type='application/xml', sitemap_url_name='django.contrib.sitemaps.views.sitemap')
    
  409. 
    
  410. The sitemap framework also has the ability to create a sitemap index that
    
  411. references individual sitemap files, one per each section defined in your
    
  412. ``sitemaps`` dictionary. The only differences in usage are:
    
  413. 
    
  414. * You use two views in your URLconf: :func:`django.contrib.sitemaps.views.index`
    
  415.   and :func:`django.contrib.sitemaps.views.sitemap`.
    
  416. * The :func:`django.contrib.sitemaps.views.sitemap` view should take a
    
  417.   ``section`` keyword argument.
    
  418. 
    
  419. Here's what the relevant URLconf lines would look like for the example above::
    
  420. 
    
  421.     from django.contrib.sitemaps import views
    
  422. 
    
  423.     urlpatterns = [
    
  424.         path('sitemap.xml', views.index, {'sitemaps': sitemaps},
    
  425.              name='django.contrib.sitemaps.views.index'),
    
  426.         path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
    
  427.              name='django.contrib.sitemaps.views.sitemap'),
    
  428.     ]
    
  429. 
    
  430. This will automatically generate a :file:`sitemap.xml` file that references
    
  431. both :file:`sitemap-flatpages.xml` and :file:`sitemap-blog.xml`. The
    
  432. :class:`~django.contrib.sitemaps.Sitemap` classes and the ``sitemaps``
    
  433. dict don't change at all.
    
  434. 
    
  435. If all sitemaps have a ``lastmod`` returned by
    
  436. :meth:`Sitemap.get_latest_lastmod` the sitemap index will have a
    
  437. ``Last-Modified`` header equal to the latest ``lastmod``.
    
  438. 
    
  439. You should create an index file if one of your sitemaps has more than 50,000
    
  440. URLs. In this case, Django will automatically paginate the sitemap, and the
    
  441. index will reflect that.
    
  442. 
    
  443. If you're not using the vanilla sitemap view -- for example, if it's wrapped
    
  444. with a caching decorator -- you must name your sitemap view and pass
    
  445. ``sitemap_url_name`` to the index view::
    
  446. 
    
  447.     from django.contrib.sitemaps import views as sitemaps_views
    
  448.     from django.views.decorators.cache import cache_page
    
  449. 
    
  450.     urlpatterns = [
    
  451.         path('sitemap.xml',
    
  452.              cache_page(86400)(sitemaps_views.index),
    
  453.              {'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
    
  454.         path('sitemap-<section>.xml',
    
  455.              cache_page(86400)(sitemaps_views.sitemap),
    
  456.              {'sitemaps': sitemaps}, name='sitemaps'),
    
  457.     ]
    
  458. 
    
  459. .. versionchanged:: 4.1
    
  460. 
    
  461.     Use of the ``Last-Modified`` header was added.
    
  462. 
    
  463. Template customization
    
  464. ======================
    
  465. 
    
  466. If you wish to use a different template for each sitemap or sitemap index
    
  467. available on your site, you may specify it by passing a ``template_name``
    
  468. parameter to the ``sitemap`` and ``index`` views via the URLconf::
    
  469. 
    
  470.     from django.contrib.sitemaps import views
    
  471. 
    
  472.     urlpatterns = [
    
  473.         path('custom-sitemap.xml', views.index, {
    
  474.             'sitemaps': sitemaps,
    
  475.             'template_name': 'custom_sitemap.html'
    
  476.         }, name='django.contrib.sitemaps.views.index'),
    
  477.         path('custom-sitemap-<section>.xml', views.sitemap, {
    
  478.             'sitemaps': sitemaps,
    
  479.             'template_name': 'custom_sitemap.html'
    
  480.         }, name='django.contrib.sitemaps.views.sitemap'),
    
  481.     ]
    
  482. 
    
  483. 
    
  484. These views return :class:`~django.template.response.TemplateResponse`
    
  485. instances which allow you to easily customize the response data before
    
  486. rendering. For more details, see the :doc:`TemplateResponse documentation
    
  487. </ref/template-response>`.
    
  488. 
    
  489. Context variables
    
  490. -----------------
    
  491. 
    
  492. When customizing the templates for the
    
  493. :func:`~django.contrib.sitemaps.views.index` and
    
  494. :func:`~django.contrib.sitemaps.views.sitemap` views, you can rely on the
    
  495. following context variables.
    
  496. 
    
  497. .. _sitemap-index-context-variables:
    
  498. 
    
  499. Index
    
  500. -----
    
  501. 
    
  502. The variable ``sitemaps`` is a list of objects containing the ``location`` and
    
  503. ``lastmod`` attribute for each of the sitemaps. Each URL exposes the following
    
  504. attributes:
    
  505. 
    
  506. - ``location``: The location (url & page) of the sitemap.
    
  507. - ``lastmod``: Populated by the :meth:`~Sitemap.get_latest_lastmod`
    
  508.   method for each sitemap.
    
  509. 
    
  510. .. versionchanged:: 4.1
    
  511. 
    
  512.     The context was changed to a list of objects with ``location`` and optional
    
  513.     ``lastmod`` attributes.
    
  514. 
    
  515. Sitemap
    
  516. -------
    
  517. 
    
  518. The variable ``urlset`` is a list of URLs that should appear in the
    
  519. sitemap. Each URL exposes attributes as defined in the
    
  520. :class:`~django.contrib.sitemaps.Sitemap` class:
    
  521. 
    
  522. - ``alternates``
    
  523. - ``changefreq``
    
  524. - ``item``
    
  525. - ``lastmod``
    
  526. - ``location``
    
  527. - ``priority``
    
  528. 
    
  529. The ``alternates`` attribute is available when :attr:`~Sitemap.i18n` and
    
  530. :attr:`~Sitemap.alternates` are enabled. It is a list of other language
    
  531. versions, including the optional :attr:`~Sitemap.x_default` fallback, for each
    
  532. URL. Each alternate is a dictionary with ``location`` and ``lang_code`` keys.
    
  533. 
    
  534. The ``item`` attribute has been added for each URL to allow more flexible
    
  535. customization of the templates, such as `Google news sitemaps`_. Assuming
    
  536. Sitemap's :attr:`~Sitemap.items()` would return a list of items with
    
  537. ``publication_data`` and a ``tags`` field something like this would
    
  538. generate a Google News compatible sitemap:
    
  539. 
    
  540. .. code-block:: xml+django
    
  541. 
    
  542.     <?xml version="1.0" encoding="UTF-8"?>
    
  543.     <urlset
    
  544.       xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
    
  545.       xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
    
  546.     {% spaceless %}
    
  547.     {% for url in urlset %}
    
  548.       <url>
    
  549.         <loc>{{ url.location }}</loc>
    
  550.         {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
    
  551.         {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
    
  552.         {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
    
  553.         <news:news>
    
  554.           {% if url.item.publication_date %}<news:publication_date>{{ url.item.publication_date|date:"Y-m-d" }}</news:publication_date>{% endif %}
    
  555.           {% if url.item.tags %}<news:keywords>{{ url.item.tags }}</news:keywords>{% endif %}
    
  556.         </news:news>
    
  557.        </url>
    
  558.     {% endfor %}
    
  559.     {% endspaceless %}
    
  560.     </urlset>
    
  561. 
    
  562. .. _`Google news sitemaps`: https://support.google.com/news/publisher-center/answer/9606710
    
  563. 
    
  564. Pinging Google
    
  565. ==============
    
  566. 
    
  567. You may want to "ping" Google when your sitemap changes, to let it know to
    
  568. reindex your site. The sitemaps framework provides a function to do just
    
  569. that: :func:`django.contrib.sitemaps.ping_google()`.
    
  570. 
    
  571. .. function:: ping_google(sitemap_url=None, ping_url=PING_URL, sitemap_uses_https=True)
    
  572. 
    
  573.     ``ping_google`` takes these optional arguments:
    
  574. 
    
  575.     * ``sitemap_url`` - The absolute path to your site's sitemap (e.g.,
    
  576.       :file:`'/sitemap.xml'`).
    
  577. 
    
  578.       If this argument isn't provided, ``ping_google`` will perform a reverse
    
  579.       lookup in your URLconf, for URLs named
    
  580.       ``'django.contrib.sitemaps.views.index'`` and then
    
  581.       ``'django.contrib.sitemaps.views.sitemap'`` (without further arguments) to
    
  582.       automatically determine the sitemap URL.
    
  583. 
    
  584.     * ``ping_url`` - Defaults to Google's Ping Tool:
    
  585.       https://www.google.com/webmasters/tools/ping.
    
  586. 
    
  587.     * ``sitemap_uses_https`` - Set to ``False`` if your site uses ``http``
    
  588.       rather than ``https``.
    
  589. 
    
  590.     :func:`ping_google` raises the exception
    
  591.     ``django.contrib.sitemaps.SitemapNotFound`` if it cannot determine your
    
  592.     sitemap URL.
    
  593. 
    
  594. .. admonition:: Register with Google first!
    
  595. 
    
  596.     The :func:`ping_google` command only works if you have registered your
    
  597.     site with `Google Search Console`_.
    
  598. 
    
  599. .. _`Google Search Console`: https://search.google.com/search-console/welcome
    
  600. 
    
  601. One useful way to call :func:`ping_google` is from a model's ``save()``
    
  602. method::
    
  603. 
    
  604.     from django.contrib.sitemaps import ping_google
    
  605. 
    
  606.     class Entry(models.Model):
    
  607.         # ...
    
  608.         def save(self, force_insert=False, force_update=False):
    
  609.             super().save(force_insert, force_update)
    
  610.             try:
    
  611.                 ping_google()
    
  612.             except Exception:
    
  613.                 # Bare 'except' because we could get a variety
    
  614.                 # of HTTP-related exceptions.
    
  615.                 pass
    
  616. 
    
  617. A more efficient solution, however, would be to call :func:`ping_google` from a
    
  618. cron script, or some other scheduled task. The function makes an HTTP request
    
  619. to Google's servers, so you may not want to introduce that network overhead
    
  620. each time you call ``save()``.
    
  621. 
    
  622. Pinging Google via ``manage.py``
    
  623. --------------------------------
    
  624. 
    
  625. .. django-admin:: ping_google [sitemap_url]
    
  626. 
    
  627. Once the sitemaps application is added to your project, you may also
    
  628. ping Google using the ``ping_google`` management command::
    
  629. 
    
  630.     python manage.py ping_google [/sitemap.xml]
    
  631. 
    
  632. .. django-admin-option:: --sitemap-uses-http
    
  633. 
    
  634. Use this option if your sitemap uses ``http`` rather than ``https``.