Django站点地图亿级URL量下动态QuerySet生成分页类问询
解决方案
核心思路是通过Python动态类创建能力+闭包批量生成分片Sitemap类,无需手动编码每个分片,实现逻辑如下:
1. 完整sitemap.py实现代码
# sitemap.py from django.contrib.sitemaps import Sitemap from appname.models import Passage import datetime import math # 公共配置常量 PER_SITEMAP_LIMIT = 10000 SITEMAP_COMMON_ATTRS = { "changefreq": "hourly", "priority": 1.0, "protocol": "http", "lastmod": datetime.datetime.now() } # 查询总数据量,计算分片总数,过亿量级建议将count结果做缓存,避免每次请求都触发全表计数 total_count = Passage.objects.count() sitemap_count = math.ceil(total_count / PER_SITEMAP_LIMIT) # 存储所有动态生成的Sitemap类的字典,直接供urls.py使用 sitemaps = {} for idx in range(sitemap_count): offset = idx * PER_SITEMAP_LIMIT limit = offset + PER_SITEMAP_LIMIT # 定义当前分片的items方法,用默认参数固定offset/limit避免闭包变量捕获问题 def items(self, offset=offset, limit=limit): # 必须固定排序,避免分片出现重复/遗漏数据,推荐用自增主键排序 return Passage.objects.order_by('id').all()[offset:limit] # 动态创建Sitemap子类,命名规则和你原有规则保持一致:Page000001、Page000002... sitemap_cls = type( f"Page{idx+1:06d}", (Sitemap,), { **SITEMAP_COMMON_ATTRS, "items": items } ) # 存入字典,key和原有命名规则保持一致 sitemaps[f"ps_file_{idx+1:06d}"] = sitemap_cls
2. urls.py配置
无需再逐个导入Sitemap子类,直接导入上面生成的sitemaps字典即可:
# urls.py from django.contrib.sitemaps.views import sitemap from appname.sitemaps import sitemaps urlpatterns = [ # 其他路由 path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'), ]
注意事项
- QuerySet必须添加固定排序规则,否则数据库返回结果顺序不确定,会导致不同分片出现重复URL、部分URL遗漏的问题。
- 如果需要更精准的更新时间,可将lastmod改为类方法,取单条内容的更新时间,示例:
def lastmod(self, obj): return obj.updated_at
将上述方法添加到SITEMAP_COMMON_ATTRS中即可生效。
内容的提问来源于stack exchange,提问作者Banjo De Koya
相关产品推荐
相关产品推荐

