之前在django制作站点地图介绍了超过5万条站点地图如何制作,但是最近在做优化工作的时候发现有些问题,例如,我想同时建立CBA和NBA两个索引文件,所以按照上次的步骤键入了如下代码:
#urls.py
path("Nba_sitemap.xml", views.index, {"sitemaps": Nba_sitemaps}),
path("Nba_<section>_sitemap.xml", views.sitemap, {"sitemaps": Nba_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
path("Cba_sitemap.xml", views.index, {"sitemaps": Cba_sitemaps}),
path("Cba_<section>_sitemap.xml", views.sitemap, {"sitemaps": Cba_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
结果发现无论访问的是Nba_sitemap.xml路径还是Cba_sitemap.xml路径,二者展现的页面索引均为同一种路径(<loc>中的路径格式,上文中为Cba_<section>_sitemap.xml),尽管可以很明显的看到二者提取的模型页数不一样(即数量/内容其实取到了正确的模型/表,但前面展示出来的路径会被后面覆盖掉),查阅了django.contrib.sitemaps.views源码,逐步排查,是因为sitemap_url_name参数的原因
#来源 from django.contrib.sitemaps import views
# 源代码
@x_robots_tag
def index(request, sitemaps,
template_name='sitemap_index.xml', content_type='application/xml',
sitemap_url_name='django.contrib.sitemaps.views.sitemap'):
req_protocol = request.scheme
req_site = get_current_site(request)
sites = [] # all sections' sitemap URLs
for section, site in sitemaps.items():
# For each section label, add links of all pages of its sitemap
# (usually generated by the `sitemap` view).
if callable(site):
site = site()
protocol = req_protocol if site.protocol is None else site.protocol
sitemap_url = reverse(sitemap_url_name, kwargs={'section': section})
absolute_url = '%s://%s%s' % (protocol, req_site.domain, sitemap_url)
sites.append(absolute_url)
# Add links to all pages of the sitemap.
for page in range(2, site.paginator.num_pages + 1):
sites.append('%s?p=%s' % (absolute_url, page))
return TemplateResponse(request, template_name, {'sitemaps': sites},
content_type=content_type)
因为时间关系,没有接着往下去研究了,因为我只是想要让站点地图文件展示正确的索引,干脆在站点地图xml文件中进行修改,直接说解决方案吧。
使用sys模块找到python路径,在site-packages中的django模块找到contrib/sitemaps/templates文件夹下面的sitemap.xml和sitemap_index.xml(可以打开看看,里面的内容并不复杂),将这两份文件拷贝到Django的Templates目录下备用。
新建过滤器sitemapProcess用于处理路径url,需要注意的是过滤器的第一个参数始终为其左边的值,而定义的链接b需始终位于url.py中的最后一行
# custom_filters.py
@register.filter("sitemapProcess")
def pro(value, country):
a = country + "_sitemap"
b = "cba_sitemap"
x = value.replace(b, a)
return x
复制一份sitemap_index.xml文件,重命名为ball_sitemap_index.xml,键入如下代码,利用request获取路径中的参数,并将其作为变量pre_xml 传入到sitemapProcess过滤器中,进行替换:
# ball_sitemap_index.xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% load custom_filters %}
{% with request.path|cut:"_sitemap.xml"|cut:"/" as pre_xml %}
{% for location in sitemaps %}<sitemap>
<loc>{{location|sitemapProcess:pre_xml}}</loc>
<lastmod>{% now "Y-m-d\T00:00:00\Z" %}</lastmod>
</sitemap> {% endfor %}</sitemapindex>
{% endwith %}
一般来讲,站点地图索引页链接都不会很多,所以替换起来也不会太影响性能。
这种方法在我看来,有点low,后续再来改造。
更新:
站点地图的问题,之前的做法实在是太low了,优化了一下。主要是将索引文件index和站点地图sitemap进行了分离,新建了一个all_sitemaps字典专门用于展现站点地图,这样后续再增加站点地图时,就很轻松了。
#urls.py
nba_index = {
'nba': nbaSitemap,
}
nba_date_index = {
'nba_date': DateOfnba,
}
cba_index = {
'cba': cbaSitemap,
}
cba_date_index = {
'cba_date': DateOfcba,
}
# 上方有多少section,这里就需要添加多少section
all_sitemaps={
'nba': nbaSitemap,
'nba_date':DateOfnba,
'cba': cbaSitemap,
'cba_date': DateOfcba,
}
urlpatterns = [
# ---- views.index ----
path("nba_sitemap.xml", views.index, {"sitemaps": nba_index}),
path("nba_date_sitemap.xml", views.index, {"sitemaps": nba_date_index}),
path("cba_sitemap.xml", views.index, {"sitemaps": cba_index}),
path("cba_date_sitemap.xml", views.index, {"sitemaps": cba_date_index }),
# ---- views.sitemaps ----
path("<section>_sitemap.xml", views.sitemap, {"sitemaps": all_sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
]
参阅:
https://docs.djangoproject.com/en/3.2/ref/contrib/sitemaps/
# 自制过滤器
https://mp.weixin.qq.com/s?__biz=MzU5OTEzOTM1Mg==&mid=2247483867&idx=1&sn=409d9678a730abb7d758409e4a1c4983&chksm=feb834acc9cfbdba2eef44e8aa509a4f93290108967841f7322ed91914e59061350f1470187c&token=485447628&lang=zh_CN#rd