站点地图框架

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

概述

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

Django 站点地图框架通过让您在 Python 代码中表达此信息来自动创建此 XML 文件。

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

安装

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

  1. 'django.contrib.sitemaps'添加到您的INSTALLED_APPS 设置中。

  2. 确保您的TEMPLATES 设置包含一个DjangoTemplates 后端,其APP_DIRS 选项设置为True。它默认情况下就在那里,因此您只需要在更改该设置后才需要更改此设置。

  3. 确保您已安装sites framework

(注意:站点地图应用程序不会安装任何数据库表。它需要进入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[source]

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

items[source]

必填。 返回对象序列QuerySet的方法。框架不关心对象的具体*类型*;重要的是这些对象会被传递给location()lastmod()changefreq()priority()方法。

location[source]

可选。 方法或属性。

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

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

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

  • 正确:'/foo/bar/'

  • 错误:'example.com/foo/bar/'

  • 错误:'https://example.com/foo/bar/'

如果没有提供location,框架将调用由items()返回的每个对象的get_absolute_url()方法。

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

lastmod

可选。 方法或属性。

如果是方法,它应该接受一个参数——由items()返回的对象——并返回该对象的最后修改日期/时间,表示为datetime

如果是属性,它的值应该是一个datetime,表示由items()返回的*每个*对象的最后修改日期/时间。

如果sitemap中的所有项目都有lastmod,则由views.sitemap()生成的sitemap将具有一个等于最新lastmodLast-Modified标头。您可以激活ConditionalGetMiddleware以使Django对带有If-Modified-Since标头的请求做出适当的响应,这将防止在sitemap未更改时发送它。

paginator[source]

可选。

此属性返回Paginator用于items()。如果您批量生成sitemap,则可能需要将其重写为缓存属性以避免多次调用items()

changefreq

可选。 方法或属性。

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

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

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

  • 'always'

  • 'hourly'

  • 'daily'

  • 'weekly'

  • 'monthly'

  • 'yearly'

  • 'never'

priority

可选。 方法或属性。

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

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

priority的示例值:0.41.0。页面的默认优先级为0.5。详情请参阅sitemaps.org 文档

protocol

可选。

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

Django 5.0 中已更改

在较旧的版本中,在请求上下文之外构建的sitemap的默认协议为'http'

limit

可选。

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

i18n

可选。

一个布尔属性,定义是否应使用所有LANGUAGES生成此sitemap的URL。默认为False

languages

可选。

一个序列,包含用于在启用i18n时生成备用链接的语言代码。默认为LANGUAGES

alternates

可选。

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

x_default

可选。

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

get_latest_lastmod()[source]

可选。 返回 lastmod 最新返回值的方法。此函数用于向 站点地图索引上下文变量 添加 lastmod 属性。

默认情况下,get_latest_lastmod() 返回

get_languages_for_item(item)[source]

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

快捷方式

站点地图框架为常见情况提供了一个便捷类

class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)[source]

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

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

示例

这是一个使用 URLconfGenericSitemap 示例

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.xml 文件,该文件引用 sitemap-flatpages.xmlsitemap-blog.xmlSitemap 类和 sitemaps 字典根本没有改变。

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

如果你的某个站点地图的 URL 超过 50,000 个,则应创建一个索引文件。在这种情况下,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",
    ),
]

模板定制

如果你希望为网站上可用的每个站点地图或站点地图索引使用不同的模板,可以通过 URLconf 将 template_name 参数传递给 sitemapindex 视图。

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="https://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>
返回顶部