Django中使用Sitemap的方法讲解及示例

Django附带了一个高级站点地图生成框架来创建站点地图XML文件。

概述

站点地图是您网站上的一个 XML 文件,用于告知搜索引擎索引器您的网页更改频率以及某些网页相对于您网站上的其他网页的“重要性”。此信息可帮助搜索引擎将您的网站编入索引。

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

它的工作方式很像Django的联合框架。要创建站点地图,请编写一个sitemap类,并在网址中指向该类。

安装

要安装站点地图应用,请按以下步骤操作:

  1. 添加到您的INSTALLED_APPS设置。'django.contrib.sitemaps'
  2. 确保 TEMPLATES 设置包含其选项设置为 的后端。默认情况下,它在那里,因此您只需要在更改该设置时更改此设置即可。
    INSTALLED_APPS = [
        'category.apps.CategoryConfig',#分类
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'django.contrib.sitemaps'#sitemaps
    ]

     

  3. 确保已安装站点框架

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

初始化

views.sitemap(请求站点地图部分=无template_name='站点地图.xml'content_type='application/xml')

要在 Django 网站上激活站点地图生成,请将此行添加到项目/urls.py

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位于/content/sitemap.xml ,它可能仅引用以/content/开头的网址。

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

Sitemap

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

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

站点地图类必须为 子类 。它们可以位于代码库中的任何地方。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

注意:

Sitemap类引用

类 Sitemap

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

items

必填。返回一个或多个对象序列的方法。框架不关心它们是什么类型的对象;重要的是这些对象被传递到 location()lastmod()changefreq() 和 priority() 方法。QuerySet

location

自选。方法或属性。

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

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

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

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

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

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

lastmod

自选。方法或属性。

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

如果它是一个属性,则其值应为日期时间,表示 items() 返回的每个对象的上次修改日期/时间。

如果站点地图中的所有项目都具有 lastmod,则 views.sitemap() 生成的站点地图将具有与 latest 相同的标头。您可以激活 ConditionalGetMiddleware,使 Django 对带有标头的请求做出适当的响应,如果站点地图没有更改,则会阻止发送站点地图。Last-ModifiedlastmodIf-Modified-Since

paginator

自选。

此属性返回 items() 的分页器。如果您批量生成站点地图,则可能需要将其覆盖为缓存属性,以避免多次调用。items()

changefreq

自选。方法或属性。

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

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

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

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

priority

自选。方法或属性。

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

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

优先级的示例值:、 。页面的默认优先级为 。有关详细信息,请参阅 sitemaps.org 文档0.41.00.5

protocol

自选。

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

自版本 4.0 起已弃用:在 Django 5.0 中,在请求上下文之外构建的站点地图的默认协议将从 更改为 。'http''https'

limit

自选。

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

i18n

自选。

一个布尔属性,用于定义是否应使用您的所有语言生成此站点地图的 URL。缺省值为 。False

languages

Django 3.2 中的新功能。

自选。

启用 i18n 时用于生成备用链接的语言代码序列。默认为语言

alternates

Django 3.2 中的新功能。

自选。

布尔属性。当与 i18n 结合使用时,生成的 URL 将具有一个使用 hreflang 属性指向其他语言版本的备用链接列表。缺省值为 。False

x_default

Django 3.2 中的新功能。

自选。

布尔属性。当备用链接生成的备用链接将包含值为 LANGUAGE_CODE 的回退条目时。缺省值为 。Truehreflang="x-default"False

快捷方式

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

类 info_dict, 优先级 = 无, 更改频率 = 无, 协议 = 无GenericSitemap)

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

优先级changefreq 和协议关键字参数允许为所有 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'),
]

静态视图的站点地图

通常,您希望搜索引擎爬网程序对既不是对象详细信息页面也不是平面页面的视图编制索引。解决方案是在站点地图的方法中显式列出这些视图的 URL 名称,并调用 reverse()。例如:itemslocation

# 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 行的外观:

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.xmlsitemap-flatpages.xmlsitemap-blog.xmlsitemaps

如果您的某个站点地图的网址超过 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'),
]

模板定制

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

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 实例,允许您在渲染之前轻松自定义响应数据。有关更多详细信息,请参阅模板响应文档

上下文变量

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

指数

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

网站地图

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

  • alternates
  • changefreq
  • item
  • lastmod
  • location
  • priority

启用 i18n 和备用项时该属性可用。它是每个 URL 的其他语言版本(包括可选的x_default回退)的列表。每个备选方案都是一个带有 和 键的字典。alternateslocationlang_code

Django 3.2 中的更改:已添加该属性。alternates

已为每个网址添加了该属性,以便更灵活地自定义模板,例如 Google 新闻站点地图。假设站点地图的 items() 将返回包含项的列表,而类似如下的字段将生成与 Google 新闻兼容的站点地图:itempublication_datatags

<?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,以便告知它重新索引您的网站。站点地图框架提供了一个功能来做到这一点:django.contrib.sitemaps.ping_google()

ping_google(sitemap_url=无ping_url=PING_URLsitemap_uses_https=真)

ping_google采用以下可选参数:

  • sitemap_url- 您网站站点地图的绝对路径(例如,)。'/sitemap.xml'

    如果未提供此参数,则会在网址中对命名的网址执行反向查找,然后(无需进一步参数)自动确定站点地图网址。ping_google'django.contrib.sitemaps.views.index''django.contrib.sitemaps.views.sitemap'

  • ping_url- 默认为谷歌的Ping工具:https://www.google.com/webmasters/tools/ping
  • sitemap_uses_https- 设置为如果您的网站使用而不是 .Falsehttphttps

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

首先向谷歌注册!

ping_google() 命令仅在您向 Google Search Console 注册您的网站时才有效。

调用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()

Ping 谷歌manage.py

django-admin ping_google [sitemap_url]

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

python manage.py ping_google [/sitemap.xml]

--sitemap-uses-http

如果您的站点地图使用 而不是 .httphttps

THE END