Структура карты сайта¶
Django поставляется с высокоуровневым фреймворком генерации sitemap для создания файлов sitemap XML.
Быстрый обзор¶
Карта сайта - это XML-файл на вашем сайте, который сообщает индексаторам поисковых систем, как часто меняются ваши страницы и насколько «важны» определенные страницы по отношению к другим страницам вашего сайта. Эта информация помогает поисковым системам индексировать ваш сайт.
Фреймворк Django sitemap автоматизирует создание этого XML-файла, позволяя вам выразить эту информацию в коде Python.
Он работает так же, как syndication framework в Django. Чтобы создать карту сайта, напишите класс Sitemap
и укажите на него в своем URLconf.
Установка¶
Чтобы установить приложение sitemap, выполните следующие действия:
- Добавьте
'django.contrib.sitemaps'
к настройкеINSTALLED_APPS
. - Убедитесь, что ваша настройка
TEMPLATES
содержит бэкендDjangoTemplates
, чьи опцииAPP_DIRS
установлены наTrue
. Он находится там по умолчанию, поэтому вам нужно будет изменить это значение, только если вы изменили эту настройку. - Убедитесь, что вы установили
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
может представлять все записи вашего блога, а другой - все события в вашем календаре событий.
В простейшем случае все эти разделы объединяются в один 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
заголовком, который предотвратит отправку карты сайта, если она не изменилась.
-
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 4.1.
Опционально. Метод, возвращающий последнее значение, возвращенное функцией
lastmod
. Эта функция используется для добавления атрибутаlastmod
к Sitemap index context variables.По умолчанию возвращается
get_latest_lastmod()
:- Если
lastmod
является атрибутом:lastmod
. - Если
lastmod
является методом: Самый последнийlastmod
, возвращенный вызовом метода со всеми элементами, возвращеннымиSitemap.items()
.
- Если
-
get_languages_for_item
(item)[исходный код]¶ - New in Django 4.2.
Опционально. Метод, возвращающий последовательность кодов языков, для которых отображается элемент. По умолчанию
get_languages_for_item()
возвращаетlanguages
.
-
Ярлыки¶
Фреймворк sitemap предоставляет удобный класс для распространенного случая:
-
class
GenericSitemap
(info_dict, priority=None, changefreq=None, protocol=None)[исходный код]¶ Класс
django.contrib.sitemaps.GenericSitemap
позволяет создать карту сайта, передав ей словарь, который должен содержать, по крайней мере, один элементqueryset
. Этот кверисет будет использоваться для генерации элементов карты сайта. Он также может содержать записьdate_field
, которая определяет поле даты для объектов, извлеченных изqueryset
. Это поле будет использоваться для атрибутовlastmod
и методовget_latest_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:
django.contrib.sitemaps.views.index()
иdjango.contrib.sitemaps.views.sitemap()
. - Представление
django.contrib.sitemaps.views.sitemap()
должно принимать аргумент в виде ключевого словаsection
.
Вот как будут выглядеть соответствующие строки 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",
),
]
Добавлено использование заголовка 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()
для каждой карты сайта.
Контекст был изменен на список объектов с location
и необязательными lastmod
атрибутами.
Карта сайта¶
Переменная urlset
представляет собой список URL, которые должны появиться в карте сайта. Каждый URL раскрывает атрибуты, определенные в классе Sitemap
:
alternates
changefreq
item
lastmod
location
priority
Атрибут alternates
доступен, когда включены i18n
и alternates
. Он представляет собой список других языковых версий, включая необязательную альтернативу x_default
для каждого 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!
Команда ping_google()
работает только в том случае, если вы зарегистрировали свой сайт в 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 добавлено в проект, можно также выполнить ping Google с помощью команды управления ping_google
:
python manage.py ping_google [/sitemap.xml]
-
--sitemap-uses-http
¶
Используйте этот параметр, если ваша карта сайта использует http
, а не https
.