在Django中缓存其他网站的数据
假设我有一个简单的视图,需要从一个外部网站获取数据。
现在的代码大概是这样的:
def index(request):
source = urllib2.urlopen(EXTERNAL_WEBSITE_URL)
bs = BeautifulSoup.BeautifulSoup(source.read())
finalList = [] # do whatever with bs to populate the list
return render_to_response('someTemplate.html', {'finalList': finalList})
首先,这样做可以吗?
显然,这样的性能不太好。外部网站的页面很大,而我只提取其中的一小部分。我想到了两种解决方案:
- 把所有操作都做成异步的。也就是说,先加载整个页面,然后等数据获取到后再填充内容。但我不知道从哪里开始。我刚开始学习Django,之前没有做过异步的事情。
- 我不在乎这些数据每2-3分钟更新一次,所以缓存也是个不错的解决方案(这样也能省去多次请求)。我该如何实现数据的缓存呢?
3 个回答
Django有很强大的内置功能来支持缓存视图,你可以在这里查看详细信息:http://docs.djangoproject.com/en/dev/topics/cache/#topics-cache。
它可以帮助你缓存整个视图(就像你提到的那样),或者只缓存视图中某些数据的部分。还有一些设置可以控制缓存多久更新一次等等。
首先,不要急着优化。先把这个功能弄好。
然后,添加足够的日志记录,看看性能问题到底出在哪里(如果有的话)。
你可能会发现,用户的电脑是最慢的部分;从其他网站获取数据其实可能很快,尤其是当你不去加载那些 .JS 库、.CSS 文件和图片时,浏览器渲染整个页面的速度会快很多。
一旦你确定从远程获取内容确实是个问题,真的确认了。那么你需要做以下几件事。
写一个“crontab”脚本,定期去获取远程数据。
设计一个地方来缓存这些远程结果。可以选择数据库或者文件系统,选一个就行。
更新你的 Django 应用,让它从缓存(数据库或文件系统)中获取数据,而不是直接从远程网址获取。
只有在你有确凿的证据证明 urllib2 从远程网站读取数据是瓶颈的时候,才这样做。
在Django中使用缓存其实很简单,
from django.core.cache import cache
key = 'some-key'
data = cache.get(key)
if data is None:
# soupify the page and what not
cache.set(data, key, 60*60*8)
return render_to_response ...
return render_to_response
关于你的问题,你可以异步地进行缓存更新,但这样的话你需要用到像django cron这样的工具,定期更新缓存。另一方面,你也可以写一个独立的Python脚本,把从Django导入的缓存替换成memcache,这样也能正常工作。这种做法可以减少你网站可能遇到的一些性能问题,只要你知道缓存的键,就可以从缓存中取回数据。
正如Jarret所说,我建议你去看看Django的缓存文档和memcache的文档,了解更多信息。