使用Django从S3提供静态页面

3 投票
2 回答
870 浏览
提问于 2025-04-17 18:04

我打算建立一个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 个回答

0

你只需要在/static-pages/12345/这个文件夹里创建一个叫index.html的文件,它就会被使用了。

0

亚马逊的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;
}

希望这能帮到你。

撰写回答