使用Django从S3提供静态页面
我打算建立一个Django应用,用来生成并提供静态页面(可能存储在S3上)。当用户访问像 mysite.com/static-pages/12345 这样的链接时,我希望能直接提供存储在我的S3桶里的名为 12345.html 的静态文件。这个静态文件可能是我网站为用户生成的某个博客页面的静态HTML页面。
这和在Django模板中包含静态资源(比如CSS或JavaScript文件)是不一样的,因为我已经会使用Django模板和SQL数据库了——我不熟悉的是,现在我的“数据”变成了一个存储在S3上的文件,而不是数据库中的一条记录,并且我实际上不需要使用模板。
我该如何准确地获取请求的数据(也就是静态页面)并返回给用户呢?我希望在合理的范围内尽量减少性能损失,当然,如果用户能直接从S3请求他们的静态页面,那是最快的(但我不希望他们这样做)。
还有一些额外的问题: 我在其他地方看到过一个Django的flatpages应用,它把HTML页面存储在数据库中,但似乎静态HTML页面最好还是存储在像S3这样的文件系统上,对吧? 有没有办法让请求先到我的Django应用,然后由S3直接提供文件,同时让用户觉得这个文件是从我的应用来的(也就是说,浏览器的地址栏仍然显示 mysite.com/static-pages/12345,但页面并没有经过我的Django服务器)?
非常感谢!
2 个回答
你只需要在/static-pages/12345/这个文件夹里创建一个叫index.html的文件,它就会被使用了。
亚马逊的S3服务不支持URL重写(因为它不是一个网页服务器),所以你必须把请求转发到一个可以为你重写URL的网页服务器或服务。
你可以使用自己控制的网页服务器,并按照这里的说明让Apache来重写URL,但这样做似乎有点浪费,因为你本来是想加载一个静态网站。
另外,我有一个解决方案,如果你想完全在S3中操作,可能会有效:
你可以指定一个HTML文档,当用户访问的页面不存在(404错误)时,这个文档会返回给用户的浏览器。你可以创建一个小的HTML页面,检查当前的URL,然后简单地改变窗口的位置,跳转到没有.html
后缀的“重写”URL:
<html>
<script>
var slash = window.location.lastIndexOf("/");
var dot = window.location.lastIndexOf(".");
if (slash < dot) && (dot != -1) {
window.location = window.location + ".html";
}
</script>
</html>
当然,你会想让它更健壮,但大概意思就是这样。
缺点是,每次用户请求你的静态页面时,都会多一次往返请求(先请求404页面,然后再请求真正的页面)。
另外,你需要调整我上面的代码,以避免在实际URL错误时触发404循环,可以添加一些检查,比如:
var loopcheck = window.location.IndexOf(".html");
if (lookcheck != -1) {
window.location = "real404.html";
return;
}
希望这能帮到你。