站点地图框架 — Django 文档
站点地图框架
Django 带有一个高级站点地图生成框架,可以轻松创建 站点地图 XML 文件。
概况
站点地图是您网站上的一个 XML 文件,它告诉搜索引擎索引器您的页面更改的频率以及某些页面相对于您网站上的其他页面的“重要性”。 此信息有助于搜索引擎为您的网站编制索引。
Django 站点地图框架通过让你用 Python 代码表达这些信息以自动创建这个 XML 文件。
它的工作原理很像 Django 的 联合框架 。 要创建站点地图,只需编写一个 Sitemap 类并在您的 URLconf 中指向它。
安装
要安装站点地图应用,请按照以下步骤进行:
- 将
'django.contrib.sitemaps'
添加到您的 :setting:`INSTALLED_APPS` 设置。 - 确保您的 :setting:`TEMPLATES` 设置包含一个
DjangoTemplates
后端,其APP_DIRS
选项设置为True
。 默认情况下它就在那里,因此如果您更改了该设置,则只需更改它。 - 确保您已安装 站点框架 。
(注意:站点地图应用程序不安装任何数据库表。 它需要进入 :setting:`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
应该是一个将短节标签(例如 blog
或 news
)映射到其 Sitemap 类(例如 [ X137X] 或 NewsSitemap
)。 它还可以映射到 Sitemap 类(例如,BlogSitemap(some_var)
)的 实例 。
Sitemap 类
Sitemap 类是一个简单的 Python 类,表示站点地图中条目的“部分”。 例如,一个 Sitemap 类可以表示您的 Weblog 的所有条目,而另一个可以表示您的事件日历中的所有事件。
在最简单的情况下,所有这些部分都集中在一个 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
注意:
- changefreq 和 priority 分别是
<changefreq>
和<priority>
元素对应的类属性。 它们可以作为函数调用,如示例中的 lastmod。 - items() 只是一个返回对象的 序列 或
QuerySet
的方法。 返回的对象将传递给与站点地图属性对应的任何可调用方法(location、lastmod、changefreq 和 priority)。 - lastmod 应该返回一个
datetime
。 - 此示例中没有 location 方法,但您可以提供它以指定对象的 URL。 默认情况下, location() 在每个对象上调用
get_absolute_url()
并返回结果。
Sitemap 类参考
- class Sitemap
Sitemap
类可以定义以下方法/属性:- items
必需。 返回对象的 序列 或
QuerySet
的方法。 框架并不关心它们是什么 type 对象; 重要的是这些对象被传递到 location()、lastmod()、changefreq() 和 priority()方法。
- location
可选。 方法或属性。
如果它是一个方法,它应该返回由 items() 返回的给定对象的绝对路径。
如果它是一个属性,它的值应该是一个字符串,表示用于 items() 返回的 every 对象的绝对路径。
在这两种情况下,“绝对路径”是指不包含协议或域的 URL。 例子:
好:
'/foo/bar/'
差:
'example.com/foo/bar/'
如果未提供 location,则框架将调用 items() 返回的每个对象上的
get_absolute_url()
方法。要指定
'http'
以外的协议,请使用 protocol。
- lastmod
可选。 方法或属性。
如果它是一个方法,它应该接受一个参数——一个由 items() 返回的对象——并返回该对象的最后修改日期/时间作为一个
datetime
。如果它是一个属性,它的值应该是一个
datetime
,表示 items() 返回的 every 对象的最后修改日期/时间。如果站点地图中的所有项目都有 lastmod,则由 views.sitemap() 生成的站点地图将有一个
Last-Modified
标头,等于最新的lastmod
]。 您可以激活 ConditionalGetMiddleware 以使 Django 正确响应带有If-Modified-Since
标头的请求,这将阻止发送未更改的站点地图。
- changefreq
可选。 方法或属性。
如果它是一个方法,它应该接受一个参数——一个由 items() 返回的对象——并将该对象的更改频率作为字符串返回。
如果它是一个属性,它的值应该是一个字符串,表示 items() 返回的 every 对象的更改频率。
changefreq 的可能值,无论您使用方法还是属性,都是:
'always'
'hourly'
'daily'
'weekly'
'monthly'
'yearly'
'never'
- priority
可选。 方法或属性。
如果它是一个方法,它应该接受一个参数——一个由 items() 返回的对象——并以字符串或浮点数形式返回该对象的优先级。
如果它是一个属性,它的值应该是一个字符串或浮点数,表示 items() 返回的 every 对象的优先级。
priority 的示例值:
0.4
、1.0
。 页面的默认优先级为0.5
。 有关更多信息,请参阅 sitemaps.org 文档 。
- protocol
可选的。
此属性定义站点地图中 URL 的协议(
'http'
或'https'
)。 如果未设置,则使用请求站点地图的协议。 如果站点地图是在请求上下文之外构建的,则默认值为'http'
。
- limit
可选的。
此属性定义站点地图每个页面上包含的最大 URL 数。 其值不应超过
50000
的默认值,这是站点地图协议中允许的上限。
- i18n
可选的。
一个布尔属性,用于定义是否应使用所有 :setting:`LANGUAGES` 生成此站点地图的 URL。 默认值为
False
。
捷径
站点地图框架为常见的情况提供了一个方便的类:
- class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)
django.contrib.sitemaps.GenericSitemap 类允许您通过传递一个字典来创建站点地图,该字典必须至少包含一个
queryset
条目。 此查询集将用于生成站点地图的项目。 它还可能有一个date_field
条目,为从queryset
检索的对象指定日期字段。 这将用于生成的站点地图中的 lastmod 属性。priority、changefreq 和 protocol 关键字参数允许为所有 URL 指定这些属性。
示例
下面是一个使用 GenericSitemap 的 URLconf 示例:
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 中使用了两个视图: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}),
path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'),
]
这将自动生成引用 sitemap-flatpages.xml
和 sitemap-blog.xml
的 sitemap.xml
文件。 Sitemap 类和 sitemaps
dict 根本没有改变。
如果您的站点地图之一包含超过 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'),
]
自定义模板
如果您希望为站点上可用的每个站点地图或站点地图索引使用不同的模板,您可以通过将 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 文档 。
索引
变量 sitemaps
是每个站点地图的绝对 URL 列表。
Sitemap
变量 urlset
是应该出现在站点地图中的 URL 列表。 每个 URL 公开在 Sitemap 类中定义的属性:
changefreq
item
lastmod
location
priority
为每个 URL 添加了 item
属性,以允许更灵活地自定义模板,例如 Google 新闻站点地图 。 假设站点地图的 items() 将返回一个包含 publication_data
和一个 tags
字段的项目列表,类似这样的内容将生成一个与 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>
通知谷歌
当您的站点地图更改时,您可能希望“ping”谷歌,让它知道重新索引您的站点。 站点地图框架提供了一个函数来做到这一点: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
- 默认为 Google 的 Ping 工具:https://www.google.com/webmasters/tools/ping。sitemap_uses_https
- 如果您的站点使用http
而不是https
,则设置为False
。
ping_google() 如果无法确定您的站点地图 URL,则会引发异常
django.contrib.sitemaps.SitemapNotFound
。2.2 新功能: 添加了
sitemap_uses_https
参数。 旧版本的 Django 总是使用http
作为站点地图的 URL。
调用 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
然而,更有效的解决方案是从 cron 脚本或其他一些计划任务调用 ping_google()。 该函数向 Google 的服务器发出 HTTP 请求,因此您可能不想在每次调用 save()
时引入该网络开销。
通过 manage.py Ping Google
将站点地图应用程序添加到您的项目后,您还可以使用 ping_google
管理命令 ping Google:
python manage.py ping_google [/sitemap.xml]
2.2 版中的新功能。
如果您的站点地图使用 http
而不是 https
,请使用此选项。