网站地图框架

Django附带了一个高级的网站地图生成框架,可以轻松地创建sitemap XML文件。

概述¶ T0>

网站地图是您网站上的XML文件,它告诉搜索引擎索引器您网页的变化频率,以及某些网页与您网站上其他网页的关系。 这些信息有助于搜索引擎索引您的网站。

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

它和Django的syndication framework非常相似。 要创建站点地图,只需写一个Sitemap类并指向它在URLconf中。

安装¶ T0>

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

  1. 'django.contrib.sitemaps'添加到INSTALLED_APPS设置中。
  2. Make sure your TEMPLATES setting contains a DjangoTemplates backend whose APP_DIRS options is set to True. 它在默认情况下,所以你只需要改变这个,如果你已经改变了这个设置。
  3. 确保你已经安装了sites framework

(注意:站点地图应用程序不安装任何数据库表。 它需要进入INSTALLED_APPS的唯一原因是Loader()模板加载器可以找到默认模板。

初始化¶ T0>

观点。sitemaprequestsitemapssection = Nonetemplate_name ='sitemap.xml' t4>,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时建立一个站点地图。

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

站点地图视图需要额外的必需参数: { '站点地图': 站点地图}. sitemaps should be a dictionary that maps a short section label (e.g., blog or news) to its Sitemap class (e.g., BlogSitemap or 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 and priority are class attributes corresponding to <changefreq> and <priority> elements, respectively. 它们可以作为函数被调用,例如lastmod
  • items() is simply a method that returns a list of objects. 返回的对象将传递给任何对应于站点地图属性(locationlastmodchangefreqpriority
  • lastmod should return a datetime.
  • 本例中没有location方法,但是您可以提供它以指定对象的URL。 By default, location() calls get_absolute_url() on each object and returns the result.

Sitemap类别参考

Sitemap[source]

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

items[source]

需要。 一个返回对象列表的方法。 The framework doesn’t care what type of objects they are; all that matters is that these objects get passed to the location(), lastmod(), changefreq() and priority() methods.

location[source]

可选的。 方法或属性。

如果是方法,它应该返回由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/'
  • Bad: 'example.com/foo/bar/'
  • 不好:'https://example.com/foo/bar/'

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

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

的lastmod T0> ¶ T1>

可选的。 方法或属性。

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

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

如果站点地图中的所有项目都有一个lastmod,那么由views.sitemap()生成的站点地图将具有一个Last-Modified最新的lastmod 您可以激活ConditionalGetMiddleware使Django正确地响应具有If-Modified-Since标头的请求,这将防止发送站点地图,如果它没有改变。

的changefreq T0> ¶ T1>

可选的。 方法或属性。

如果是一个方法,它应该有一个参数 - 一个由items()返回的对象 - 并以字符串的形式返回对象的更改频率。

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

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

  • '总是'
  • “每小时”
  • '日常'
  • '每周'
  • “每月”
  • '每年'
  • '决不'
优先 T0> ¶ T1>

可选的。 方法或属性。

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

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.41.0 一个页面的默认优先级是0.5 有关更多信息,请参阅sitemaps.org文档

协议 T0> ¶ T1>

可选的。

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

限制 T0> ¶ T1>

可选的。

该属性定义站点地图每个页面上包含的URL的最大数量。 其值不应超过50000的默认值,即Sitemaps协议中允许的上限。

I18N T0> ¶ T1>

可选的。

一个布尔属性,用于定义是否应该使用所有的LANGUAGES生成此站点地图的URL。 默认值是False

快捷键¶ T0>

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

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

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

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

Django 2.0新增功能:

添加了protocol关键字参数。

实施例¶ T0>

以下是使用GenericSitemapURLconf的示例:

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名称,并在sitemap的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')
]

创建站点地图索引

观点。indexrequestsitemapstemplate_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}),
    path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap'),
]

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

如果您的一个站点地图拥有超过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'),
]

模板定制

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

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 documentation

上下文变量

在定制index()sitemap()视图的模板时,可以依赖以下上下文变量。

指数¶ T0>

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

网站地图¶ T0>

变量urlset是应该出现在站点地图中的URL列表。 每个网址都公开Sitemap类中定义的属性:

  • 的changefreq
  • 项目
  • 的lastmod
  • 位置
  • 优先

已为每个网址添加了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="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

你可能想要在你的网站地图改变时“ping”谷歌,让它知道重新索引你的网站。 sitemaps框架提供了一个功能:django.contrib.sitemaps.ping_google()

ping_google()[source]

ping_google() takes an optional argument, sitemap_url, which should be the absolute path to your site’s sitemap (e.g., '/sitemap.xml'). If this argument isn’t provided, ping_google() will attempt to figure out your sitemap by performing a reverse looking in your URLconf.

ping_google() raises the exception django.contrib.sitemaps.SitemapNotFound if it cannot determine your sitemap URL.

先注册Google!

ping_google()命令仅在您使用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().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() The function makes an HTTP request to Google’s servers, so you may not want to introduce that network overhead each time you call save().

通过manage.py 来Ping Google

django-admin ping_google [sitemap_url]

一旦Sitemaps应用程序被添加到您的项目中,您也可以使用ping_google管理命令ping Google:

python manage.py ping_google [/sitemap.xml]