Google App Engine 静态页面 Python 2.5 目录等

0 投票
3 回答
1475 浏览
提问于 2025-04-17 09:33

我刚开始接触这个,打算把我的东西从一个付费的网络服务迁移到GAE(只是静态页面,没有动态内容)。相信我,我花了无数个小时试图让这个工作,但现在遇到了瓶颈,我总是只能实现一个结果,而另一个结果就无法实现,反之亦然。

我相信这个问题的答案很简单,我可能违反了一些基本原则。我想要的是,应用引擎页面(mygaeid.appspot.com)能提供一个静态的首页,同时其他页面可以通过添加后缀来访问,比如 mygaeid.appspot.com/oranges.html、mygaeid.appspot.com/grapes.html 等等。

我无法做到这一点,要么我能在添加后缀后访问其他页面,比如 mygaeid.appspot.com/apples.html、mygaeid.appspot.com/oranges.html,但首页却无法访问;要么我稍微修改一下yaml文件,首页(mygaeid.appspot.com)可以正常工作,但无法访问带有后缀的其他页面(mygaeid.appspot.com/oranges.html 等等)。

下面是py文件(abcdefg.py),它在接下来的两个不同的yaml文件中是通用的:

import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template

class MainHandler(webapp.RequestHandler):
  def get (self, q):
    if q is None:
      q = 'htmdir/apples.html'

    path = os.path.join (os.path.dirname (__file__), q)
    self.response.headers ['Content-Type'] = 'text/html'
    self.response.out.write (template.render (path, {}))


def main ():
  application = webapp.WSGIApplication ([('/(.*html)?', MainHandler)], debug=True)
  util.run_wsgi_app (application)

if __name__ == '__main__':
  main ()

使用下面的yaml,首页(mygaeid.appspot.com)可以完美工作(显示apples.html的内容),但我无法在添加后缀后访问页面,比如 mygaeid.appspot.com/apples.html 或 mygaeid.appspot.com/static/htmdir/apples.html 等等,一旦我添加后缀就无法工作。在目录(htmdir)中,我放置了apples.html和其他html页面,比如oranges.html等,但使用这个yaml我无法访问任何页面。

application: mygaeid
version: 1
runtime: python
api_version: 1

handlers:
- url: /(.*\.(html))
  static_files: static/htmdir/\1
  upload: static/htmdir/(.*\.(html))

- url: /css
  static_dir: css

- url: /js
  static_dir: js

- url: /images
  static_dir: images

- url: .*
  script: abcdefg.py

如果我按照以下方式修改yaml,那么首页(mygaeid.appspot.com)就无法工作,但当我添加后缀时,它就能完美工作,比如 mygaeid.appspot.com/apples.html;mygaeid.appspot.com/oranges.html 等等都能正常显示相应的页面:

- url: /(.*\.(html))
  static_files: htmdir/\1
  upload: htmdir/(.*\.(html))

最后,如果我完全不使用目录,并且使用相同的abcdefg.py(没有目录),那么以下这个非常简单的yaml实际上能实现我想要的结果,但所有文件都堆在根目录下,这样就显得很乱。

application: mygaeid
version: 1
runtime: python
api_version: 1

handlers:
- url: /(.*\.(png|js|css))
  static_files: \1
  upload: (.*\.(png|js|css))

- url: .*
  script: abcedfg.py

如果能帮我解决这个问题,我将非常感激。谢谢!


谢谢wooble,也谢谢dave,我又回去仔细查看了日志。Wooble的解决方案有效,但我需要把包含html的htmdir放在一个叫做static的目录里。GAE是一个很棒(而且免费的)静态网站解决方案。

非常感谢你们的帮助和反馈。

SiteDirectory
-mygaeid
  -static
    -htmdir
  -js
  -css
  -images
 app.yaml
 index.yaml
(py file was removed)

3 个回答

0

这样工作的原因是有技术上的考虑

app.yaml 配置文件的工作方式非常简单,就是从上到下按顺序执行。

匹配的顺序如下:

1. - url: /(.*\.(html))
  static_files: static/htmdir/\1
  upload: static/htmdir/(.*\.(html))

2. - url: /css
  static_dir: css

3. - url: /js
  static_dir: js

4. - url: /images
  static_dir: images

5. - url: .*
  script: abcdefg.py

简单来说,如果文件后缀是 .html,那么在第一步就会被匹配,并把请求从 mygaeid.appspot.com/.html 转到 mygaeid.appspot.com/htmdir/.html。第五步的 *.html 处理程序不会被触发,因为所有的 *.html 路径已经被占用了。

另外,正如其他回答所提到的,标记为静态的目录在你的应用处理程序中是无法本地访问的。我会尝试解释一下技术原因。

app.yaml 作为 GAE 的反向代理配置文件。静态文件只有在上传时才会改变,所以它们非常适合缓存。通过在部署时立即将静态文件推送到缓存服务器,GAE 提高了加载性能,并减少了应用服务器的负担。

静态请求被单独计算,并且费用比普通应用请求低是有原因的。每次你请求一个静态文件,实际上就是从 GAE 的 CDN 拉取这个文件。如果你只请求静态文件,那么你的服务器根本就没有启动的必要。

这种方法的明显缺点是,这些文件并不在和你的应用同一个服务器上,所以你不能直接在应用中获取或上传它们。

注意:也遵循了其他回答的内容。不要把你的模板文件夹标记为静态。当你的应用加载模板时——而不是从相邻目录获取——它会发送一个网络请求,从远程位置获取文件。显然,从远程获取文件而不是本地文件会增加加载时间和延迟。

1

Woobie的回答是对的。让我换个说法。

当你把.html文件放在static_files里时,这些文件会由专门处理静态内容的服务来提供。你的应用程序是看不到这些文件的。应用程序只能看到被称为资源的文件。

Django的模板必须是资源,而不是静态文件。否则,应用程序就无法找到它们,template.render(path, ...这个命令就会出错。

解决你问题的下一步是(如果你还没做的话)更新你的帖子,展示一下你当前的app.yaml文件,并告诉我们应用程序日志中报告了什么。

4

如果你在app.yaml文件中把某些文件声明为静态文件,那么这些文件就不能被你的应用程序处理了。

不过,如果这些文件确实是静态的,使用django模板引擎去“渲染”它们就有点多余了;你只需要在app.yaml中添加一些映射,就可以直接显示这些静态文件,比如可以为根目录(/)显示apples.html:

application: mygaeid
version: 1
runtime: python
api_version: 1

handlers:
- url: /(.*\.html)
  static_files: static/htmdir/\1
  upload: static/htmdir/.*\.html

- url: /css
  static_dir: css

- url: /js
  static_dir: js

- url: /images
  static_dir: images

- url: /
  static_files: static/htmdir/apples.html
  upload: static/htmdir/apples\.html

(不需要任何python文件)

撰写回答