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

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 классы

Класс Sitemap - это простой класс Python, который представляет «раздел» записей в вашей карте сайта. Например, один класс Sitemap может представлять все записи вашего Weblog, а другой - все события в вашем календаре событий.

В простейшем случае все эти разделы объединяются в один 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, не включающий протокол или домен. Примеры:

  • Хорошо: '/foo/bar/'
  • Плохо: 'example.com/foo/bar/'
  • Плохо: '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 заголовком, который предотвратит отправку карты сайта, если она не изменилась.

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'.

limit

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

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

i18n

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

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

Ярлыки

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

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

Класс django.contrib.sitemaps.GenericSitemap позволяет создать карту сайта, передав ей словарь, который должен содержать по крайней мере queryset запись. Этот набор запросов будет использоваться для генерации элементов карты сайта. Он также может содержать запись date_field, которая определяет поле даты для объектов, извлеченных из queryset. Это поле будет использоваться для атрибута lastmod в сгенерированной карте сайта.

Ключевые аргументы 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}),
    path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap'),
]

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

Вам следует создать индексный файл, если одна из ваших карт сайта содержит более 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'),
]

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

Если вы хотите использовать другой шаблон для каждой карты сайта или индекса карты сайта, доступных на вашем сайте, вы можете указать его, передав параметр 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'
    }),
    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 представляет собой список абсолютных URL-адресов к каждой из карт сайта.

Карта сайта

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

  • changefreq
  • item
  • lastmod
  • location
  • priority

Атрибут 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.
  • 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 вашей карты сайта.

New in Django 2.2:

Был добавлен аргумент sitemap_uses_https. Старые версии Django всегда использовали http для URL карты сайта.

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

Команда ping_google() работает только в том случае, если вы зарегистрировали свой сайт с помощью Google Webmaster Tools.

Одним из полезных способов вызова 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
New in Django 2.2.

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

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