标签:+= lis 简单的 字典 ima 页面 位置 als 统一
对于百度、360等搜索引擎,后台有提交网站地图(sitemap)的需求。以百度为例,规定网站地图的格式为xml或者txt,并且有比较严格的格式要求,django自带sitemap功能,但是使用起来比较麻烦,相关教程也非常少,还不够灵活,这里自定义一个类,实例化之后以比较灵活的方式来生成网站地图。
根节点为urlset,由url包裹其他标签这个后端渲染的变量有loc、lastmod、changefreq、priority这几种,以下的模板因为没有必要使用lastmod,所以既没有留位置渲染,也没有用if做空值判断,可以根据需求自己添加。
<urlset>
{% for item in obj_sitemap %}
<url>
<loc>{{ item.loc }}</loc>
{% if item.changefreq %}
<changefreq>{{ item.changefreq }}</changefreq>
{% endif %}
{% if item.priority %}
<priority>{{ item.priority }}</priority>
{% endif %}
</url>
{% endfor %}
</urlset>
这个sitemap类的主要思路是将字典渲染成xml格式,可以单独写出来导入,也可以直接写到views.py中。类实例化之后将参数通过函数转化成字典传递到列表中,到了所有需要的url都集中之后,统一渲染出来。
class Sitemap:
‘‘‘
· loc:完整的url,带有协议名http/https、域名
· lastmod:最近的更新时间,格式如 2020-11-11
· changefreq:页面的更新频率,有这几种 always、hourly、daily、weekly、monthly、yearly、never
· priority:优先级,从1-0越来越高,比如优先级最高的首页是1
‘‘‘
# 注意,实例化的时候,网站的协议默认为http,正常情况下http会被重定向到https,但是https未经设置不能重定向到http,浏览器还会报ssl警告
def __init__(self,request,template,protocol="http"):
self.request = request
# 网站前缀,如果对象实例化的时候,protocol是https的话,url的前缀就是https://domain
self.site = protocol + "://" + request.META["HTTP_HOST"]
self.template = template
self.li_query = []
# 传入参数自动构造成字典
def construct_dict(self,loc=None,lastmod=None,changefreq=None,priority=None):
if loc:
self.li_query.append({
"loc":loc,
"lastmod":lastmod,
"changefreq":changefreq,
"priority":priority
})
# 执行渲染,需要注意的是,渲染出的结果是一个xml文件,因此要设置content_type="text/xml"
def execute(self):
return render(self.request,"sitemap.xml",{"obj_sitemap":self.li_query},content_type="text/xml")
以下代码的models指的是django的app的models.py,因为已经导入到views.py,这里就不过多赘述
# 因为生成网站地图是开销比较大的,特地开启缓存功能
from django.views.decorators.cache import cache_page
# 缓存页面刷新时间为12小时
@cache_page(60*60*12)
def sitemap(request):
# 实例化sitemap对象
obj_sitemap = Sitemap(request,"sitemap.xml",protocol="http")
# 类似于首页的页面,直接使用对象添加参数的方法添加
obj_sitemap.construct_dict(
loc=obj_sitemap.site+reverse("index"),
changefreq="daily",
priority="1"
)
# 文章页,orm中的audit为审核状态(入库但不发布),因此用exclude先排除,其余都遍历一次
for item in models.Airticle.objects.exclude(audit=False).order_by("-id"):
obj_sitemap.construct_dict(
# 本项目文章页的路由名称是detail,读取数据库条目的参数是id,构造出来的url结构就是 https://domain/detail/?id=index/
loc=obj_sitemap.site+reverse("detail")+"?id="+str(item.id),
changefreq="yearly",
priority="0.4"
)
# 列表页,文章按照主题分类聚合成列表页。这里的Types是所有的文章类型,每一种类型按照id来区分,用page来切片实现分页
# 遍历
for item in models.Types.objects.all():
whole_count = item.airtical_set.all().exclude(audit=False).count()
# 每个列表页展现几篇文章,这里就写几,这里是9
page_count = 9
# 因为有分页,需要单独采用取模运算来计算数量,page表示这个列表页有几页,extra表示余数,如果余数不为0,那么page就应该+1,因为要单独加一页展现最后不到9的几篇文章
page,extra = divmod(whole_count,page_count)
if extra != 0:
page += 1
# 这个项目后端使用get取值,列表页的url结构是 https://domain/listpage/?id=index&page=index ,如果只有一页,就不存在page参数,所以第一页单独加一个判断,要用到字符串格式化
for i in range(1,page+1):
if i == 1:
page_tail = ""
else:
page_tail = f"&page={i}"
obj_sitemap.construct_dict(
# url结构
loc=obj_sitemap.site+reverse("news_list")+f"?id={item.id}{page_tail}",
changefreq="weekly",
priority="0.6"
)
# 最后一步,用render渲染
return obj_sitemap.execute()
django自定义类,实现简单的sitemap(网站地图)功能
标签:+= lis 简单的 字典 ima 页面 位置 als 统一
原文地址:https://www.cnblogs.com/himan47/p/14685377.html