yokon's blog

Flask不渲染显示sitemap.xml

2017.12.11

嫌弃Wordprcess笨重速度慢,而且不支持markdown语法,就用hexo驱动做静态博客。又觉得hexo麻烦,不是很喜欢,就想着全凭自己的喜好来做一个功能齐全的博客网站,于是就有了这个小站。使用Flask开发Mysql存储,再加上自己一点前端基础写的样式,感兴趣的可以参看源码。

由于项目前后写的时间不是很长,有很多功能写的不是很好,后续会继续改进。也欢迎pull requests或者提供建议。

send_from_directory方法

本篇文章写一些在开发过程中遇到的一些问题。由于之前的博客网站地图sitemap.xml都是本身平台生成,自己开发的肯定需要自己实现。但是平常flask显示模版文件都是使用render_template方法。但是这么做会自己转换htmlxml文件为网页信息,并不会显示原生的文件格式。

那要怎样才能只显示原生静态文件呢,比如robots.txt,sitemap.xml。我的第一想法是直接将静态文件放在根目录,然后使用make_response函数将文件内容读取出来,并将其填入响应对象Response object中。然后将他返回。

@app.route('/robots.txt', methods=['GET'])
def robots():
	response = make_response(open('robots.txt').read())
	response.headers["Content-type"] = "text/html"
	return response

这么做是可以实现的,但是这么实现总觉得很蠢。如果用js来对网页渲染后的内容进行返回源文件的方式,也很蠢。我想应该有更加优雅的实现方法。就找到了flasksend_static_file方法,可以直接返回静态文件。参考官方文档:here

@app.route('/robots.txt')
def robots():
	return app.send_static_file('robots.txt')

这是将文件放在程序目录下,但是一般情况下我们是将静态文件放在static目录下的,所以我们更加应该使用send_from_directory方法。

@app.route('/robots.txt')
def robots():
	return send_from_directory('static', 'robots.txt')

生成站点地图

站点地图的基本样式

<?xml version="1.0" encoding="UTF-8"?>

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

   <url>

	  <loc>http://www.example.com/</loc>

	  <lastmod>2005-01-01</lastmod>

	  <changefreq>monthly</changefreq>

	  <priority>0.8</priority>

   </url>

</urlset> 

我们只要根据这种样式在每次请求的时候自动生成就可以了。

import os

def get_sitemap(posts):
	# 参数posts是文章模型哦,组成文章对应的url就可以了
	header = '<?xml version="1.0" encoding="UTF-8"?> '+ '\n' + \
		'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
	footer = '</urlset>'
	contents = []
	body = ''
	if posts:
		for post in posts:
			content = '  <url>' + '\n' + \
				'    <loc>http://www.yukunweb.com/' + str(post.timestampInt) + '/' + post.url_name + '/' + '</loc>' + '\n' + \
				'    <lastmod>' + post.timestamp + '</lastmod>' + '\n' + \
				'  </url>'
			contents.append(content)
		for content in contents:
			body = body + '\n' + content
		sitemap = header + '\n' + body + '\n' + footer
		return sitemap
	return None

def save_file(sitemap):
	isExists = os.path.exists(os.path.join("/home/root/YuBlog/app/static", 'sitemap.xml'))
	if not isExists:
		with open('/home/root/YuBlog/app/static/sitemap.xml', 'w') as f:
			f.write(sitemap)
	else:
		os.remove('/home/root/YuBlog/app/static/sitemap.xml')
		with open('/home/root/YuBlog/app/static/sitemap.xml', 'w') as f:
			f.write(sitemap)

利用内置的os模块生成sitemap.xml在每次请求替换已有的文件就行了。