网站地图框架

Django 附带了一个高级网站地图生成框架,用于创建 网站地图 XML 文件。

概述

网站地图是网站上的一个 XML 文件,它告诉搜索引擎索引器你的页面更改的频率以及某些页面相对于网站上其他页面的“重要性”。这些信息有助于搜索引擎索引你的网站。

Django 网站地图框架通过让你用 Python 代码表示这些信息,自动创建此 XML 文件。

它的工作方式与 Django 的 联合框架 非常相似。要创建网站地图,请编写一个 Sitemap 类,并在你的 URLconf 中指向它。

安装

要安装网站地图应用程序,请按照以下步骤操作

  1. 'django.contrib.sitemaps' 添加到你的 INSTALLED_APPS 设置中。
  2. 确保你的 TEMPLATES 设置包含一个 DjangoTemplates 后端,其 APP_DIRS 选项设置为 True。默认情况下它就在那里,因此只有在你更改了该设置时才需要更改此设置。
  3. 确保已安装 sites 框架

(注意:站点地图应用程序不会安装任何数据库表。它需要进入 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,它可能只引用以 /content/ 开头的 URL。

网站地图视图需要一个额外的必需参数:{'sitemaps': sitemaps}sitemaps 应该是一个字典,它将一个简短的节标签(例如,blognews)映射到其 Sitemap 类(例如,BlogSitemapNewsSitemap)。它还可以映射到 Sitemap 类的实例(例如,BlogSitemap(some_var))。

Sitemap

Sitemap 类是一个 Python 类,它表示网站地图中条目的“节”。例如,一个 Sitemap 类可以表示博客的所有条目,而另一个类可以表示活动日历中的所有活动。

在最简单的情况下,所有这些节都会合并到一个 sitemap.xml 中,但也可以使用框架生成引用单个网站地图文件的网站地图索引,每个节一个。(请参阅下面的 创建网站地图索引。)

Sitemap 类必须是 django.contrib.sitemaps.Sitemap 的子类。它们可以存在于代码库中的任何位置。

示例

假设您有一个博客系统,其中包含一个 Entry 模型,并且您希望您的网站地图包含指向您各个博客文章的所有链接。以下是您的网站地图类可能的样子

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

注意

  • changefreqpriority 是分别对应于 <changefreq><priority> 元素的类属性。它们可以作为函数进行调用,就像 lastmod 在示例中一样。
  • items() 是一个返回 序列 或对象 QuerySet 的方法。返回的对象将传递给对应于网站地图属性的任何可调用方法(locationlastmodchangefreqpriority)。
  • lastmod 应返回 datetime
  • 此示例中没有 location 方法,但你可以提供该方法以指定对象的 URL。默认情况下,location() 会对每个对象调用 get_absolute_url() 并返回结果。

Sitemap 类参考

class Sitemap

Sitemap 类可以定义以下方法/属性

items

必需。返回 序列 或对象的 QuerySet 的方法。框架并不关心它们是什么类型的对象;重要的是这些对象会传递给 location()lastmod()changefreq()priority() 方法。

位置

可选。方法或属性。

如果它是方法,它应返回 items() 返回的给定对象的绝对路径。

如果它是属性,其值应为一个字符串,表示 items() 返回的每个对象的绝对路径。

在这两种情况下,“绝对路径”表示不包含协议或域的 URL。示例

  • 好:'/foo/bar/'
  • 差:'example.com/foo/bar/'
  • 差:'https://example.com/foo/bar/'

如果未提供 位置,框架将对 items() 返回的每个对象调用 get_absolute_url() 方法。

要指定 'http' 以外的协议,请使用 协议

上次修改

可选。方法或属性。

如果它是方法,它应采用一个参数 - items() 返回的对象 - 并返回该对象的上次修改日期/时间,格式为 datetime

如果它是属性,其值应为 datetime,表示 items() 返回的每个对象的上次修改日期/时间。

如果网站地图中的所有项都具有 lastmod,则由 views.sitemap() 生成的网站地图将具有等于最新 lastmodLast-Modified 头。您可以激活 ConditionalGetMiddleware,以便让 Django 适当地响应带有 If-Modified-Since 头的请求,该头将阻止发送未更改的网站地图。

paginator

可选。

此属性返回 items()Paginator。如果您批量生成网站地图,您可能希望将其覆盖为一个缓存属性,以避免多次 items() 调用。

changefreq

可选。方法或属性。

如果它是一个方法,它应该接受一个参数——一个由 items() 返回的对象——并返回该对象的更改频率,作为字符串。

如果它是一个属性,其值应为一个字符串,表示由 items() 返回的每个对象的更改频率。

无论您使用的是方法还是属性,changefreq 的可能值为

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

可选。方法或属性。

如果它是一个方法,它应该采用一个参数——由 items() 返回的对象——并返回该对象的优先级,可以是字符串或浮点数。

如果它是一个属性,它的值应该是表示由 items() 返回的每个对象的优先级的字符串或浮点数。

priority 的示例值:0.41.0。页面的默认优先级为 0.5。有关更多信息,请参阅 sitemaps.org 文档

protocol

可选。

此属性定义站点地图中 URL 的协议('http''https')。如果未设置,则使用请求站点地图的协议。如果在请求的上下文中外部构建站点地图,则默认值为 'https'

在 Django 5.0 中更改

在较旧版本中,在请求的上下文中外部构建的站点地图的默认协议为 'http'

limit

可选。

此属性定义站点地图每页包含的最大 URL 数。其值不应超过默认值 50000,这是 站点地图协议 中允许的上限。

i18n

可选。

一个布尔属性,定义是否使用所有 LANGUAGES 为此站点地图生成 URL。默认值为 False

languages

可选。

当启用 i18n 时,用于生成备用链接的 序列 语言代码。默认为 LANGUAGES

alternates

可选。

一个布尔属性。与 i18n 结合使用时,生成的 URL 将分别具有一个备用链接列表,指向使用 hreflang 属性 的其他语言版本。默认值为 False

x_default

可选。

一个布尔属性。当 True 时,由 alternates 生成的备用链接将包含一个 hreflang="x-default" 回退项,其值为 LANGUAGE_CODE。默认值为 False

get_latest_lastmod()

可选。返回 lastmod 返回的最新值的方法。此函数用于将 lastmod 属性添加到 Sitemap 索引上下文变量

默认情况下,get_latest_lastmod() 返回

get_languages_for_item(item)
Django 4.2 中的新增功能。

可选。返回显示该项的语言代码序列的方法。默认情况下,get_languages_for_item() 返回 languages

快捷方式

Sitemap 框架为常见情况提供了一个便捷类

GenericSitemap(info_dict, priority=, changefreq=, protocol=)

通过向 django.contrib.sitemaps.GenericSitemap 类传递一个至少包含一个 queryset 条目的字典,你可以创建一个站点地图。此查询集将用于生成站点地图的项目。它还可以有一个 date_field 条目,该条目指定从 queryset 检索的对象的日期字段。这将用于生成站点地图中的 lastmod 属性和 get_latest_lastmod() 方法。

关键字参数 prioritychangefreqprotocol 允许为所有 URL 指定这些属性。

示例

下面是一个使用 GenericSitemapURLconf 示例

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",
    ),
]

静态视图的站点地图

通常,您希望搜索引擎爬虫索引既不是对象详细页面也不是扁平页面的视图。解决方案是在 items 中明确列出这些视图的 URL 名称,并在站点地图的 location 方法中调用 reverse()。例如

# 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')

站点地图框架还具有创建站点地图索引的能力,该索引引用各个站点地图文件,每个文件对应于 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-flatpages.xmlsitemap-blog.xmlsitemap.xml 文件。Sitemap 类和 sitemaps 字典根本不会更改。

如果所有站点地图都有 Sitemap.get_latest_lastmod() 返回的 lastmod,则站点地图索引将具有等于最新 lastmodLast-Modified 头。

如果您的某个站点地图有超过 50,000 个 URL,则应创建一个索引文件。在这种情况下,Django 会自动对站点地图进行分页,并且索引将反映这一点。

如果您没有使用香草站点地图视图(例如,如果它用缓存装饰器包装),则必须为您的站点地图视图命名,并将 sitemap_url_name 传递给索引视图

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",
    ),
]

模板定制

如果您希望为您的网站上可用的每个站点地图或站点地图索引使用不同的模板,则可以通过向 sitemapindex 视图通过 URLconf 传递 template_name 参数来指定它

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 文档

上下文变量

在为 index()sitemap() 视图定制模板时,您可以依赖以下上下文变量。

索引

变量 sitemaps 是一个包含 locationlastmod 属性的每个网站地图的对象列表。每个 URL 暴露以下属性

  • location:网站地图的位置(url 和页面)。
  • lastmod:由 get_latest_lastmod() 方法填充,适用于每个网站地图。

网站地图

变量 urlset 是应出现在网站地图中的 URL 列表。每个 URL 暴露 Sitemap 类中定义的属性

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

当启用 i18nalternates 时,alternates 属性可用。它是一个其他语言版本列表,包括每个 URL 的可选 x_default 回退。每个备用都是一个包含 locationlang_code 键的字典。

为每个 URL 添加了 item 属性,以便更灵活地自定义模板,例如 Google 新闻站点地图。假设 Sitemap 的 items() 将返回一个包含 publication_datatags 字段的项列表,如下所示,将生成一个与 Google 新闻兼容的站点地图

<?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>
返回顶部