Skip to main content

Sitemap框架

Django提供了一个高级站点地图生成框架,使创建 sitemap XML文件变得容易。

概述

网站地图是您网站上的一个XML文件,用于告知搜索引擎索引器您的网页的变化频率以及某些网页与您网站上的其他网页之间的“重要性”。此信息有助于搜索引擎为您的网站编制索引。

Django sitemap框架通过让您在Python代码中表达此信息,自动创建此XML文件。

它的工作原理很像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

url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
    name='django.contrib.sitemaps.views.sitemap')

这告诉Django在客户端访问 /sitemap.xml 时构建一个站点地图。

Sitemap文件的名称不重要,但位置为。搜索引擎将只会索引您网站地图中当前网址级别及以下级别的链接。例如,如果 sitemap.xml 位于您的根目录中,它可以引用您站点中的任何URL。但是,如果您的站点地图位于 /content/sitemap.xml,则它只能引用以 /content/ 开头的网址。

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

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

注意:

  • changefreqpriority 是分别对应于 <changefreq><priority> 元素的类属性。它们可以作为函数调用,如 lastmod 在示例中。

  • items() 只是一个返回对象列表的方法。返回的对象将传递给与网站地图属性(locationlastmodchangefreqpriority)相对应的任何可调用方法。

  • lastmod 应返回 datetime

  • 在此示例中没有 location 方法,但您可以提供它以便指定对象的URL。默认情况下,location() 在每个对象上调用 get_absolute_url() 并返回结果。

Sitemap 类引用

class Sitemap[源代码]

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

items[源代码]

需要。 返回对象列表的方法。框架不关心它们的 type 对象;所有重要的是这些对象被传递给 location()lastmod()changefreq()priority() 方法。

location[源代码]

可选的。 方法或属性。

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

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

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

  • 好:'/foo/bar/'

  • 坏:'example.com/foo/bar/'

  • 坏:'https://example.com/foo/bar/'

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

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

lastmod

可选的。 方法或属性。

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

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

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

changefreq

可选的。 方法或属性。

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

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

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

  • 'always'

  • 'hourly'

  • 'daily'

  • 'weekly'

  • 'monthly'

  • 'yearly'

  • 'never'

priority

可选的。 方法或属性。

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

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

priority 的示例值:0.41.0。页面的默认优先级为 0.5。参见 sitemaps.org documentation 了解更多。

protocol

可选的。

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

limit

可选的。

此属性定义了网站地图的每个网页上包含的网址数量上限。其值不应超过 50000 的默认值,这是 Sitemaps协议 中允许的上限。

i18n

可选的。

布尔属性,用于定义是否应使用您的所有 LANGUAGES 生成此网站地图的网址。默认值为 False

快捷方式

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

class GenericSitemap[源代码]

django.contrib.sitemaps.GenericSitemap 类允许您通过传递一个必须包含至少一个 queryset 条目的字典来创建一个站点地图。此查询集将用于生成站点地图的项目。它还可以具有指定用于从 queryset 检索的对象的日期字段的 date_field 条目。这将用于生成的站点地图中的 lastmod 属性。您还可以将 prioritychangefreq 关键字参数传递给 GenericSitemap 构造函数,以指定所有URL的这些属性。

这里是使用 GenericSitemapURLconf 的示例:

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

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

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

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

静态视图的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.conf.urls import url
from django.contrib.sitemaps.views import sitemap

from .sitemaps import StaticViewSitemap
from . import views

sitemaps = {
    'static': StaticViewSitemap,
}

urlpatterns = [
    url(r'^$', views.main, name='main'),
    url(r'^about/$', views.about, name='about'),
    url(r'^license/$', views.license, name='license'),
    # ...
    url(r'^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 = [
    url(r'^sitemap\.xml$', views.index, {'sitemaps': sitemaps}),
    url(r'^sitemap-(?P<section>.+)\.xml$', views.sitemap, {'sitemaps': sitemaps},
        name='django.contrib.sitemaps.views.sitemap'),
]

这将自动生成引用 sitemap-flatpages.xmlsitemap-blog.xmlsitemap.xml 文件。 Sitemap 类和 sitemaps dict不改变。

如果您的其中一个Sitemap包含超过50,000个网址,就应该建立索引档。在这种情况下,Django会自动对网站地图分页,索引会反映出来。

如果您不使用vanilla网站地图视图 - 例如,如果它包含缓存装饰器 - 您必须命名您的网站地图视图并将 sitemap_url_name 传递到索引视图:

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

urlpatterns = [
    url(r'^sitemap\.xml$',
        cache_page(86400)(sitemaps_views.index),
        {'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
    url(r'^sitemap-(?P<section>.+)\.xml$',
        cache_page(86400)(sitemaps_views.sitemap),
        {'sitemaps': sitemaps}, name='sitemaps'),
]

模板定制

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

from django.contrib.sitemaps import views

urlpatterns = [
    url(r'^custom-sitemap\.xml$', views.index, {
        'sitemaps': sitemaps,
        'template_name': 'custom_sitemap.html'
    }),
    url(r'^custom-sitemap-(?P<section>.+)\.xml$', views.sitemap, {
        'sitemaps': sitemaps,
        'template_name': 'custom_sitemap.html'
    }, name='django.contrib.sitemaps.views.sitemap'),
]

这些视图返回 TemplateResponse 实例,允许您在渲染之前轻松自定义响应数据。有关详细信息,请参阅 TemplateResponse文档

上下文变量

当自定义 index()sitemap() 视图的模板时,可以依赖于以下上下文变量。

指数

变量 sitemaps 是每个Sitemap的绝对网址列表。

Sitemap

变量 urlset 是应显示在网站地图中的网址列表。每个URL公开如 Sitemap 类中定义的属性:

  • changefreq

  • item

  • lastmod

  • location

  • priority

已为每个URL添加了 item 属性,以允许更灵活地定制模板,例如 Google news sitemaps。假设Sitemap的 items() 会传回含有 publication_datatags 栏位的项目清单,因此这会产生Google新闻相容的Sitemap:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
  xmlns="http://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>

正在Ping Google

您可能希望在您的Sitemap更改时“ping”Google,让其知道重新构建您的网站。站点地图框架提供了一个函数来做:django.contrib.sitemaps.ping_google()

ping_google()[源代码]

ping_google() 采用可选参数 sitemap_url,它应是网站站点地图的绝对路径(例如 '/sitemap.xml')。如果未提供此参数,ping_google() 将尝试通过在URLconf中执行反向查找来找出您的站点地图。

如果 ping_google() 无法确定您的站点地图网址,则会引发 django.contrib.sitemaps.SitemapNotFound 异常。

先注册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(Entry, self).save(force_insert, force_update)
        try:
            ping_google()
        except Exception:
            # Bare 'except' because we could get a variety
            # of HTTP-related exceptions.
            pass

然而,更有效的解决方案是从cron脚本或某些其他计划任务调用 ping_google()。该函数向Google的服务器发出HTTP请求,因此您可能不想在每次调用 save() 时引入该网络开销。

通过 manage.py Ping Google

django-admin ping_google [sitemap_url]

将Sitemap应用程序添加到您的项目后,您还可以使用 ping_google 管理命令ping Google:

python manage.py ping_google [/sitemap.xml]