Структура карты сайта

Django поставляется с высокоуровневым фреймворком генерации sitemap для создания файлов sitemap XML.

Быстрый обзор

Карта сайта - это XML-файл на вашем сайте, который сообщает индексаторам поисковых систем, как часто меняются ваши страницы и насколько «важны» определенные страницы по отношению к другим страницам вашего сайта. Эта информация помогает поисковым системам индексировать ваш сайт.

Фреймворк Django sitemap автоматизирует создание этого XML-файла, позволяя вам выразить эту информацию в коде Python.

Он работает так же, как syndication framework в Django. Чтобы создать карту сайта, напишите класс Sitemap и укажите на него в вашем URLconf.

Установка

Чтобы установить приложение sitemap, выполните следующие действия:

  1. Добавьте 'django.contrib.sitemaps' к настройке INSTALLED_APPS.
  2. Убедитесь, что ваша настройка TEMPLATES содержит бэкенд DjangoTemplates, чьи опции APP_DIRS установлены на True. Он находится там по умолчанию, поэтому вам нужно будет изменить это значение, только если вы изменили эту настройку.
  3. Убедитесь, что вы установили sites framework.

(Примечание: приложение sitemap не устанавливает никаких таблиц базы данных. Единственная причина, по которой оно должно попасть в INSTALLED_APPS - это чтобы загрузчик шаблонов Loader() смог найти шаблоны по умолчанию)

Инициализация

views.sitemap(request, sitemaps, section=None, template_name='sitemap.xml', content_type='application/xml')

Чтобы активировать генерацию карты сайта на вашем сайте Django, добавьте эту строку в ваш URLconf:

from django.contrib.sitemaps.views import sitemap

path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
     name='django.contrib.sitemaps.views.sitemap')

Это указывает Django создавать карту сайта, когда клиент обращается к /sitemap.xml.

Имя файла карты сайта не имеет значения, но важно его расположение. Поисковые системы будут индексировать ссылки в вашей карте сайта только для текущего уровня URL и ниже. Например, если файл sitemap.xml находится в корневом каталоге, он может ссылаться на любой URL вашего сайта. Однако если ваша карта сайта находится на уровне /content/sitemap.xml, она может ссылаться только на URL, начинающиеся с /content/.

Представление карты сайта принимает дополнительный, обязательный аргумент: {'sitemaps': sitemaps}. sitemaps должен быть словарем, который сопоставляет короткую метку раздела (например, blog или news) с его Sitemap классом (например, BlogSitemap или NewsSitemap). Она также может сопоставлять с экземпляром класса Sitemap (например, BlogSitemap(some_var)).

Sitemap классы

A Sitemap class is a Python class that represents a «section» of entries in your sitemap. For example, one Sitemap class could represent all the entries of your blog, while another could represent all of the events in your events calendar.

В простейшем случае все эти разделы объединяются в один sitemap.xml, но можно также использовать фреймворк для создания индекса карты сайта, который ссылается на отдельные файлы карты сайта, по одному на раздел. (См. Creating a sitemap index ниже.)

Классы Sitemap должны быть подклассами django.contrib.sitemaps.Sitemap. Они могут находиться в любом месте вашей кодовой базы.

Пример

Предположим, у вас есть система блогов с моделью Entry, и вы хотите, чтобы ваша карта сайта включала все ссылки на отдельные записи в блоге. Вот как может выглядеть ваш класс sitemap:

from django.contrib.sitemaps import Sitemap
from blog.models import Entry

class BlogSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5

    def items(self):
        return Entry.objects.filter(is_draft=False)

    def lastmod(self, obj):
        return obj.pub_date

Примечание:

  • changefreq и priority - это атрибуты класса, соответствующие элементам <changefreq> и <priority> соответственно. Их можно сделать вызываемыми функциями, как это было сделано в примере lastmod.
  • items() - это метод, который возвращает sequence или QuerySet объектов. Возвращенные объекты будут переданы любым вызываемым методам, соответствующим свойству sitemap (location, lastmod, changefreq и priority).
  • lastmod должно возвращать datetime.
  • В этом примере нет метода location, но вы можете предоставить его, чтобы указать URL для вашего объекта. По умолчанию location() вызывает get_absolute_url() на каждом объекте и возвращает результат.

Sitemap ссылка на класс

class Sitemap[исходный код]

Класс Sitemap может определять следующие методы/атрибуты:

items[исходный код]

** Требуется.** Метод, который возвращает sequence или QuerySet объектов. Фреймворку не важно, какого типа эти объекты; важно лишь то, что эти объекты передаются методам location(), lastmod(), changefreq() и priority().

location[исходный код]

Опционально. Либо метод, либо атрибут.

Если это метод, то он должен возвращать абсолютный путь для данного объекта, как возвращает items().

Если это атрибут, то его значение должно быть строкой, представляющей абсолютный путь, который следует использовать для каждого объекта, возвращаемого items().

В обоих случаях «абсолютный путь» означает URL, не включающий протокол или домен. Примеры:

  • Good: '/foo/bar/'
  • Bad: 'example.com/foo/bar/'
  • Bad: 'https://example.com/foo/bar/'

Если location не предоставлен, фреймворк вызовет метод get_absolute_url() на каждом объекте, возвращенном items().

Чтобы указать протокол, отличный от 'http', используйте protocol.

lastmod

Опционально. Либо метод, либо атрибут.

Если это метод, то он должен принимать один аргумент - объект, возвращаемый items() - и возвращать дату/время последнего изменения этого объекта в виде datetime.

Если это атрибут, то его значением должно быть datetime, представляющее дату/время последнего изменения для каждого объекта, возвращаемого items().

Если все элементы в карте сайта имеют lastmod, то карта сайта, сгенерированная views.sitemap(), будет иметь заголовок Last-Modified, равный последнему lastmod. Вы можете активировать ConditionalGetMiddleware, чтобы заставить Django реагировать соответствующим образом на запросы с If-Modified-Since заголовком, который предотвратит отправку карты сайта, если она не изменилась.

paginator

Опционально.

Это свойство возвращает Paginator для items(). Если вы генерируете карты сайта пакетно, вы можете переопределить это свойство как кэшируемое, чтобы избежать многократных вызовов items().

changefreq

Опционально. Либо метод, либо атрибут.

Если это метод, то он должен принимать один аргумент - объект, возвращаемый командой items() - и возвращать частоту изменения этого объекта в виде строки.

Если это атрибут, то его значением должна быть строка, представляющая частоту изменения каждого объекта, возвращаемого командой items().

Возможные значения для changefreq, независимо от того, используете ли вы метод или атрибут, следующие:

  • 'always'
  • 'hourly'
  • 'daily'
  • 'weekly'
  • 'monthly'
  • 'yearly'
  • 'never'
priority

Опционально. Либо метод, либо атрибут.

Если это метод, то он должен принимать один аргумент - объект, возвращаемый командой items() - и возвращать приоритет этого объекта в виде строки или float.

Если это атрибут, то его значением должна быть либо строка, либо число float, представляющее приоритет каждого объекта, возвращаемого командой items().

Пример значений для priority: 0.4, 1.0. По умолчанию приоритет страницы равен 0.5. Подробнее см. в sitemaps.org documentation.

protocol

Опционально.

Этот атрибут определяет протокол ('http' или 'https') URL-адресов в карте сайта. Если он не задан, то используется протокол, с которым карта сайта была запрошена. Если карта сайта создается вне контекста запроса, по умолчанию используется протокол 'http'.

Не рекомендуется, начиная с версии 4.0: Протокол по умолчанию для sitemaps, построенных вне контекста запроса, изменится с 'http' на 'https' в Django 5.0.

limit

Опционально.

Этот атрибут определяет максимальное количество URL-адресов, включенных на каждой странице карты сайта. Его значение не должно превышать значение по умолчанию 50000, которое является верхним пределом, допустимым в Sitemaps protocol.

i18n

Опционально.

Булев атрибут, определяющий, следует ли генерировать URL этой карты сайта, используя все ваши LANGUAGES. По умолчанию используется False.

languages

Опционально.

Значение sequence из language codes, используемое для генерации альтернативных ссылок, когда включено i18n. По умолчанию установлено значение LANGUAGES.

alternates

Опционально.

Булев атрибут. При использовании в сочетании с i18n генерируемые URL будут иметь список альтернативных ссылок, указывающих на другие языковые версии, использующие hreflang attribute. По умолчанию используется False.

x_default

Опционально.

Булев атрибут. Когда True, альтернативные ссылки, генерируемые alternates, будут содержать запись hreflang="x-default" fallback со значением LANGUAGE_CODE. По умолчанию используется значение False.

get_latest_lastmod()
New in Django Development version.

Опционально. Метод, возвращающий последнее значение, возвращенное функцией lastmod. Эта функция используется для добавления атрибута lastmod к Sitemap index context variables.

По умолчанию возвращается get_latest_lastmod():

get_languages_for_item(item, lang_code)
New in Django 4.2.

Опционально. Метод, возвращающий последовательность кодов языков, для которых отображается элемент. По умолчанию get_languages_for_item() возвращает languages.

Ярлыки

Фреймворк sitemap предоставляет удобный класс для распространенного случая:

class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)[исходный код]

The django.contrib.sitemaps.GenericSitemap class allows you to create a sitemap by passing it a dictionary which has to contain at least a queryset entry. This queryset will be used to generate the items of the sitemap. It may also have a date_field entry that specifies a date field for objects retrieved from the queryset. This will be used for the lastmod attribute and get_latest_lastmod() methods in the in the generated sitemap.

Ключевые аргументы priority, changefreq и protocol позволяют указать эти атрибуты для всех URL.

Пример

Вот пример того, как URLconf использует GenericSitemap:

from django.contrib.sitemaps import GenericSitemap
from django.contrib.sitemaps.views import sitemap
from django.urls import path
from blog.models import Entry

info_dict = {
    'queryset': Entry.objects.all(),
    'date_field': 'pub_date',
}

urlpatterns = [
    # some generic view using info_dict
    # ...

    # the sitemap
    path('sitemap.xml', sitemap,
         {'sitemaps': {'blog': GenericSitemap(info_dict, priority=0.6)}},
         name='django.contrib.sitemaps.views.sitemap'),
]

Sitemap для статических представлений

Часто требуется, чтобы поисковые машины индексировали представления, которые не являются ни страницами детализации объекта, ни плоскими страницами. Решение состоит в том, чтобы явно перечислить имена URL для этих представлений в items и вызвать reverse() в методе location карты сайта. Например:

# sitemaps.py
from django.contrib import sitemaps
from django.urls import reverse

class StaticViewSitemap(sitemaps.Sitemap):
    priority = 0.5
    changefreq = 'daily'

    def items(self):
        return ['main', 'about', 'license']

    def location(self, item):
        return reverse(item)

# urls.py
from django.contrib.sitemaps.views import sitemap
from django.urls import path

from .sitemaps import StaticViewSitemap
from . import views

sitemaps = {
    'static': StaticViewSitemap,
}

urlpatterns = [
    path('', views.main, name='main'),
    path('about/', views.about, name='about'),
    path('license/', views.license, name='license'),
    # ...
    path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap')
]

Создание индекса карты сайта

views.index(request, sitemaps, template_name='sitemap_index.xml', content_type='application/xml', sitemap_url_name='django.contrib.sitemaps.views.sitemap')

Каркас sitemap также имеет возможность создавать индекс sitemap, который ссылается на отдельные файлы sitemap, по одному на каждый раздел, определенный в вашем словаре sitemaps. Различия в использовании заключаются только в следующем:

Вот как будут выглядеть соответствующие строки URLconf для приведенного выше примера:

from django.contrib.sitemaps import views

urlpatterns = [
    path('sitemap.xml', views.index, {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.index'),
    path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap'),
]

Это автоматически создаст файл sitemap.xml, который ссылается на sitemap-flatpages.xml и sitemap-blog.xml. Классы Sitemap и диктант sitemaps не меняются вообще.

Если все карты сайта имеют lastmod, возвращаемый Sitemap.get_latest_lastmod(), индекс карты сайта будет иметь заголовок Last-Modified, равный последнему lastmod.

Вам следует создать индексный файл, если одна из ваших карт сайта содержит более 50 000 URL. В этом случае Django будет автоматически расставлять страницы в карте сайта, и индекс будет отражать это.

Если вы не используете ванильное представление sitemap - например, если оно обернуто декоратором кэширования - вы должны назвать свое представление sitemap и передать sitemap_url_name в представление index:

from django.contrib.sitemaps import views as sitemaps_views
from django.views.decorators.cache import cache_page

urlpatterns = [
    path('sitemap.xml',
         cache_page(86400)(sitemaps_views.index),
         {'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
    path('sitemap-<section>.xml',
         cache_page(86400)(sitemaps_views.sitemap),
         {'sitemaps': sitemaps}, name='sitemaps'),
]
Changed in Django Development version:

Добавлено использование заголовка Last-Modified.

Настройка шаблонов

Если вы хотите использовать другой шаблон для каждой карты сайта или индекса карты сайта, доступных на вашем сайте, вы можете указать его, передав параметр template_name в представления sitemap и index через URLconf:

from django.contrib.sitemaps import views

urlpatterns = [
    path('custom-sitemap.xml', views.index, {
        'sitemaps': sitemaps,
        'template_name': 'custom_sitemap.html'
    }, name='django.contrib.sitemaps.views.index'),
    path('custom-sitemap-<section>.xml', views.sitemap, {
        'sitemaps': sitemaps,
        'template_name': 'custom_sitemap.html'
    }, name='django.contrib.sitemaps.views.sitemap'),
]

Эти представления возвращают экземпляры TemplateResponse, которые позволяют легко настраивать данные ответа перед рендерингом. Для более подробной информации смотрите TemplateResponse documentation.

Контекстные переменные

При настройке шаблонов для представлений index() и sitemap() вы можете полагаться на следующие контекстные переменные.

Главная

Переменная sitemaps представляет собой список объектов, содержащих атрибут location и lastmod для каждой из карт сайта. Каждый URL раскрывает следующие атрибуты:

  • location: Местоположение (url и страница) карты сайта.
  • lastmod: Заполняется методом get_latest_lastmod() для каждой карты сайта.
Changed in Django Development version:

Контекст был изменен на список объектов с location и необязательными lastmod атрибутами.

Карта сайта

Переменная urlset представляет собой список URL, которые должны появиться в карте сайта. Каждый URL раскрывает атрибуты, определенные в классе Sitemap:

  • alternates
  • changefreq
  • item
  • lastmod
  • location
  • priority

Атрибут alternates доступен, когда включены i18n и alternates. Он представляет собой список других языковых версий, включая необязательный x_default fallback, для каждого URL. Каждая альтернатива представляет собой словарь с ключами location и lang_code.

Атрибут item был добавлен для каждого URL, чтобы обеспечить более гибкую настройку шаблонов, например Google news sitemaps. Если предположить, что items() Sitemap вернет список элементов с publication_data и полем tags, то нечто подобное сгенерирует карту сайта, совместимую с Google News:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
  xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
{% spaceless %}
{% for url in urlset %}
  <url>
    <loc>{{ url.location }}</loc>
    {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
    {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
    {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
    <news:news>
      {% if url.item.publication_date %}<news:publication_date>{{ url.item.publication_date|date:"Y-m-d" }}</news:publication_date>{% endif %}
      {% if url.item.tags %}<news:keywords>{{ url.item.tags }}</news:keywords>{% endif %}
    </news:news>
   </url>
{% endfor %}
{% endspaceless %}
</urlset>

Пингование Google

Вы можете захотеть «пинговать» Google, когда ваша карта сайта меняется, чтобы сообщить ему о необходимости переиндексации вашего сайта. Фреймворк sitemaps предоставляет функцию, позволяющую сделать именно это: django.contrib.sitemaps.ping_google().

ping_google(sitemap_url=None, ping_url=PING_URL, sitemap_uses_https=True)[исходный код]

ping_google принимает эти необязательные аргументы:

  • sitemap_url - Абсолютный путь к карте сайта (например, '/sitemap.xml').

    Если этот аргумент не указан, ping_google выполнит обратный поиск в вашей URLconf для URL с именами 'django.contrib.sitemaps.views.index', а затем 'django.contrib.sitemaps.views.sitemap' (без дополнительных аргументов), чтобы автоматически определить URL sitemap.

  • ping_url - По умолчанию используется Ping Tool от Google: https://www.google.com/webmasters/tools/ping.

  • sitemap_uses_https - Установите значение False, если ваш сайт использует http, а не https.

ping_google() вызывает исключение django.contrib.sitemaps.SitemapNotFound, если не может определить URL вашей карты сайта.

Сначала зарегистрируйтесь в Google!

The ping_google() command only works if you have registered your site with Google Search Console.

Одним из полезных способов вызова ping_google() является метод save() модели:

from django.contrib.sitemaps import ping_google

class Entry(models.Model):
    # ...
    def save(self, force_insert=False, force_update=False):
        super().save(force_insert, force_update)
        try:
            ping_google()
        except Exception:
            # Bare 'except' because we could get a variety
            # of HTTP-related exceptions.
            pass

Однако более эффективным решением будет вызов ping_google() из сценария cron или другой запланированной задачи. Функция выполняет HTTP-запрос к серверам Google, поэтому вы не захотите вводить сетевые накладные расходы при каждом вызове save().

Пинг Google через manage.py

django-admin ping_google [sitemap_url]

После добавления приложения sitemaps в ваш проект вы также можете пропинговать Google, используя команду управления ping_google:

python manage.py ping_google [/sitemap.xml]
--sitemap-uses-http

Используйте этот параметр, если ваша карта сайта использует http, а не https.

Вернуться на верх