站点地图框架¶
Django 自带了一个高级站点地图生成框架来创建 sitemap XML 文件。
概况¶
站点地图是你网站上的一个 XML 文件,它告诉搜索引擎索引器你页面的变化频率,以及某些页面相对于你网站上其他页面的“重要性”。这些信息有助于搜索引擎对你的网站进行索引。
Django 站点地图框架通过让你用 Python 代码表达这些信息以自动创建这个 XML 文件。
它的工作原理很像 Django 的 联合框架。要创建一个站点地图,写一个 Sitemap 类,并将其指向你的 URLconf。
安装¶
要安装站点地图应用,请按照以下步骤进行:
将
'django.contrib.sitemaps'添加到你的INSTALLED_APPS配置中。确保你的
TEMPLATES配置中包含一个DjangoTemplates后端,其APP_DIRS选项设置为True。默认有一个后端,所以你只需要改变这个配置就可以了。确保你已经安装了
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。
sitemap 视图需要一个额外的、必要的参数:{'sitemaps': sitemaps}。sitemaps 应该是一个字典,它将一个简短的章节标签(例如,blog 或 news)映射到它的 Sitemap 类(例如,BlogSitemap 或 NewsSitemap)。也可以映射到一个 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
注意:
changefreq和priority分别是用作<changefreq>和<priority>元素的类属性。它们可以作为函数调用,就像本例中的lastmod一样。items()is a method that returns a sequence orQuerySetof objects. The objects returned will get passed to any callable methods corresponding to a sitemap property (location,lastmod,changefreq, andpriority).There is no
locationmethod in this example, but you can provide it in order to specify the URL for your object. By default,locationcallsget_absolute_url()on each object and returns the result.
Sitemap 类参考¶
- class Sitemap[source]¶
Sitemap类可以定义以下方法/属性。- items()[source]¶
Required. A method that returns a sequence or
QuerySetof objects. The framework doesn't care what type of objects they are; all that matters is that these objects get passed to thelocation,lastmod,changefreqandprioritymethods.
- location[source]¶
可选的。 方法或属性。
If it's a method, it should return the absolute path for a given object as returned by
items().If it's an attribute, its value should be a string representing an absolute path to use for every object returned by
items().在这两种情况下,“绝对路径”指的是不包含协议或域名的 URL。例如:
好的:
'/foo/bar/'不好的:
'example.com/foo/bar/'不好的:
'https://example.com/foo/bar/'
If
locationisn't provided, the framework will call theget_absolute_url()method on each object as returned byitems.如果要指定
'http'以外的协议,请使用protocol。
- lastmod¶
可选的。 方法或属性。
If it's a method, it should take one argument -- an object as returned by
items()-- and return that object's last-modified date/time as adatetime.If it's an attribute, its value should be a
datetimerepresenting the last-modified date/time for every object returned byitems().如果站点地图中的所有项目都有一个
lastmod,那么由views.sitemap()生成的站点地图将有一个Last-Modified头,等于最新的lastmod。你可以激活ConditionalGetMiddleware,让 Django 对请求做出适当的响应,并提供If-Modified-Since头,防止发送没有变化的站点地图。
- paginator[source]¶
可选的。
This property returns a
Paginatorforitems(). If you generate sitemaps in a batch you may want to override this as a cached property in order to avoid multipleitems()calls.
- changefreq¶
可选的。 方法或属性。
If it's a method, it should take one argument -- an object as returned by
items()-- and return that object's change frequency as a string.If it's an attribute, its value should be a string representing the change frequency of every object returned by
items().changefreq的可能值,无论你是使用方法还是属性,都是:'always''hourly''daily''weekly''monthly''yearly''never'
- priority¶
可选的。 方法或属性。
If it's a method, it should take one argument -- an object as returned by
items()-- and return that object's priority as either a string or float.If it's an attribute, its value should be either a string or float representing the priority of every object returned by
items().priority的示例值:0.4,1.0。页面的默认优先级是0.5。更多信息请参见 sitemaps.org documentation 。
- protocol¶
可选的。
该属性定义了站点地图中 URL 的协议(
'http'或'https')。如果未设置,则使用请求站点地图时使用的协议。如果站点地图是在没有请求上下文的情况下构建的,默认值为'https'。
- limit¶
可选的。
该属性定义了网站地图每一页所包含的 URL 的最大数量。其值不应超过默认值
50000,这是 Sitemaps protocol 中允许的上限。
- alternates¶
可选的。
一个布尔属性。当与
i18n结合使用时,生成的 URL 将有一个备用链接列表,使用 hreflang attribute 指向其他语言版本。默认为False。
- x_default¶
可选的。
一个布尔属性。当
True时,由alternates生成的备用链接将包含一个hreflang="x-default"回退条目,其值为LANGUAGE_CODE。默认值是False。
- get_latest_lastmod()[source]¶
可选项。 一个方法,返回由
lastmod返回的最新值。此函数用于向 Sitemap 索引上下文变量 添加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()方法。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},
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 字典完全没有变化。
If all sitemaps have a lastmod returned by
get_latest_lastmod() the sitemap index will have a
Last-Modified header equal to the latest lastmod.
如果你的一个网站地图有超过 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",
),
]
自定义模板¶
如果你希望为网站上的每个站点地图或站点地图索引使用不同的模板,你可以通过 URLconf 向 sitemap 和 index 视图传递一个 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 文档。
上下文变量¶
索引¶
变量 sitemaps 是一个包含每个站点地图的 location 和 lastmod 属性的对象列表。每个 URL 具有以下属性:
location:站点地图的位置(URL 和页面)。lastmod:由每个站点地图的get_latest_lastmod()方法填充。
Sitemap¶
变量 urlset 是一个应该出现在站点地图中的 URL 列表,每个 URL 都会暴露出 Sitemap 类中定义的属性。
alternateschangefreqitemlastmodlocationpriority
当 i18n 和 alternates 被启用时,alternates 属性可用。它是一个其他语言版本的列表,包括可选的 x_default 回退,对于每个 URL。每个候补是一个字典,有 location 和 lang_code 键。
The item attribute has been added for each URL to allow more flexible
customization of the templates, such as Google news sitemaps. Assuming
Sitemap's items() would return a list of items with
publication_data and a tags field something like this would
generate a Google News compatible sitemap:
<?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>