网站地图

优质
小牛编辑
134浏览
2023-12-01

Django 自带了一个高级的网站地图创建框架, 这使得创建XML格式的网站地图 变得容易。

概述

一个站点地图是一个在你网站上的用来告诉搜索引擎你的页面更新的多频繁和某些页面在你的网站中的重要关系的索引的XML文件此信息有助于搜索引擎为您的网站编制索引。

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

它的工作原理很像 Django 的联合框架。为了创建网站地图,只需编写 Sitemap 类,并在 URLconf 中指向该类。

安装

安装网站地图APP的步骤如下:

  1. INSTALLED_APPS设置中添加'django.contrib.sitemaps' .
  2. 确认你的TEMPLATES 设置包含 DjangoTemplates 后端,并将APP_DIRS 选项设置为 True. 当然默认值就是这样的,只有当你曾经修改过这些设置,才需要修改这个配置。
  3. 确认你已经安装sites framework.

(注意: 网站地图APP并不安装任何数据库表 。需要修改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')

当客服端访问 /sitemap.xml时,这将告诉Django生成一个网站地图。

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

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

Sitemap 类

Sitemap 类是一个简单的 Python 类,表示站点地图中“一部分”条目。例如,一个 Sitemap 类可以表示 Weblog 的所有条目,而另一个可以表示事件日历中的所有事件。

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

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 应返回 Python datetime 对象。
  • 在此示例中没有 location 方法,但你可以提供此方法来指定对象的 URL。默认情况下,location()在每个对象上调用get_absolute_url()并返回结果。

Sitemap 类参考

class Sitemap[source]

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

items[source]

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

location[source]

可选的. 进入一个方法或属性

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

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

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

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

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

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

lastmod

可选。方法或属性。

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

If it’s an attribute, its value should be a Python datetime.datetime object representing the last-modified date/time for every object returned by items().

New in Django 1.7.

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

changefreq

可选。方法或属性。

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

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

不管您使用方法还是属性,changefreq的可能值为:

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

priority

可选。方法或属性。

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

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

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

protocol

可选。

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

limit

可选。

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

i18n

New in Django 1.8.

可选。

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

快捷方式

对于常见的情况,Sitemap框架提供了一些方便的类:

class FlatPageSitemap[source]

自1.8版起已弃用:请改用django.contrib.flatpages.sitemaps.FlatPageSitemap

django.contrib.sitemaps.FlatPageSitemap类查看为当前SITE_ID定义的所有公开可见的flatpages(请参阅sites documentation),并在站点地图中创建一个条目。这些条目仅包含location属性 - 不是lastmodchangefreqpriority

class GenericSitemap[source]

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

以下是使用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中显式列出这些视图的网址名称,并在网站地图的location方法中调用reverse()。例如:

# sitemaps.py
from django.contrib import sitemaps
from django.core.urlresolvers 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}),
]

这将自动生成引用sitemap-flatpages.xmlsitemap-blog.xmlsitemap.xml文件。Sitemap类和sitemaps类别根本不会更改。

如果您的其中一个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参数传递到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'
    }),
]

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

上下文变量

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

指数

变量sitemaps是每个站点地图的绝对网址列表。

Sitemap

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

  • changefreq
  • item
  • lastmod
  • location
  • priority

已为每个网址添加了item属性,以允许更灵活地自定义模板,例如Google新闻站点地图。假设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="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 Google

你可能希望在 Sitemap 更改时“ping”Google,以便让其重新索引你的网站。sitemaps框架提供了一个函数:django.contrib.sitemaps.ping_google()

ping_google()[source]

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

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

先注册Google!

只有您已经使用Google网站管理员工具注册了您的网站,ping_google()命令才会生效。

调用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()时引入该网络开销。

正在通过Google Pingmanage.py

django-admin ping_google

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

python manage.py ping_google [/sitemap.xml]