在 Django 中分割一个大站点地图

split a large sitemap in django

我的 django 应用 sitemap.py 看起来像这样:

class DetailViewSitemap(Sitemap):
    priority = 0.8
    changefreq = 'hourly'

    def items(self):
        objs = MyApp.objects.all().distinct('slug')
        return objs

..我的 models.py convininetlky 定义了这样一个方法:

@models.permalink
def get_absolute_url(self):
    try:
        return ('detail', [self.slug])
    except:
        return None

一切正常,但我现在意识到 google 不允许单个站点地图中的链接超过 50k - 不幸的是我有超过 50k 的链接。

所以,我的问题是如何拆分我的站点地图,以便它在此应用程序上生成连续的站点地图?所以,我想要一些类似的东西:

http://mywebapp.com/sitemap0.xml
http://mywebapp.com/sitemap1.xml
...

..如果这可能的话!

Create an index sitemap 并且 Django 会像这样自动对详细信息站点地图进行分页:

http://mywebapp.com/sitemap-details.xml
http://mywebapp.com/sitemap-details.xml?page=1
...

解决此问题的一种方法是将大型站点地图分解为一组较小的站点地图。例如,我通过标题的第一个字母为文章构建了一个单独的站点地图。因此字母表中的每个字母都会有一个站点地图文件。如果您想使用也可以使用的字母数字字符,但在我们的例子中字母可以正常工作。 Python built-in 方法 ascii_lowercase 将 return 我们可以循环构建每个站点地图的字母字符数组。

from datetime import date
from string import ascii_lowercase
from django.contrib.sitemaps import Sitemap
from .models import Article

def build_sitemaps():
    sitemap = {}
    for char in ascii_lowercase:
        article_sitemap = ArticleSitemap(letter=char)
        sitemap[char] = article_sitemap
    return sitemap


class ArticleSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5

    def __init__(self, letter='a'):
        self.letter = letter.lower()
        super(ArticleSitemap, self).__init__()

    def items(self):
        today = date.today()
        return Article.objects.filter(
            status=Article.PUBLISHED,
            title__istartswith=self.letter,
            ).exclude(
                publish_date__gt=today,
            ).order_by('-publish_date')

下面我还添加了站点地图的缓存,这非常好。然后像这样在 urls.py 中添加站点地图:

from django.contrib.sitemaps import views as sitemaps_views                                                                                                          
from django.views.decorators.cache import cache_page 

from articles.sitemaps import build_sitemaps

urlpatterns = [
    url(r'^sitemap\.xml$', cache_page(86400)(sitemaps_views.index), {'sitemaps': build_sitemaps()}),                                                                 
    url(r'^sitemap-(?P<section>.+)\.xml$', cache_page(86400)(sitemaps_views.sitemap), {'sitemaps': build_sitemaps()},                                                
        name='django.contrib.sitemaps.views.sitemap'),
]

如果您需要有关如何使用 Sitemap Index 实现它的更多代码片段,请在我的网站 https://www.ronbeltran.com/2018/11/generating-large-xml-sitemaps-django/

中查看此 post

好吧,这是 6 年前提出的问题,但今天您可以简单地添加一个 limit:

class MovieSitemap(sitemaps.Sitemap):

    # ...

    limit = 100

   #  ...

这将生成一个索引文件和每个具有您设置的限制的站点地图:

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>http://127.0.0.1:8000/sitemap-movies.xml</loc>
    </sitemap>
    <sitemap>
        <loc>http://127.0.0.1:8000/sitemap-movies.xml?p=2</loc>
    </sitemap>
    <sitemap>
        <loc>http://127.0.0.1:8000/sitemap-movies.xml?p=3</loc>
    </sitemap>
    <sitemap>
        <loc>http://127.0.0.1:8000/sitemap-movies.xml?p=4</loc>
    </sitemap>
</sitemapindex>