在Google App Engine之外使用webapp2提供样式表

时间:2012-06-07 15:37:49

标签: python css google-app-engine static webapp2

所以我使用webapp2 / jinja2和Paste服务器成功部署了一个应用程序,但是在提供静态样式表方面遇到了麻烦。

我很幸运能够通过this method访问静态文件,以及实现我在google-fu中找到的StaticFileHandler:

import os
import mimetypes
import webapp2
import logging

class StaticFileHandler(webapp2.RequestHandler):
    def get(self, path):
        abs_path = os.path.abspath(os.path.join(self.app.config.get('webapp2_static.static_file_path', 'static'), path))
        if os.path.isdir(abs_path) or abs_path.find(os.getcwd()) != 0:
            self.response.set_status(403)
            return
        try:
            f = open(abs_path, 'r')
            self.response.headers.add_header('Content-Type', mimetypes.guess_type(abs_path)[0])
            self.response.out.write(f.read())
            f.close()
        except:
            self.response.set_status(404)

我的主应用程序路由如下:

app = webapp2.WSGIApplication([('/', HelloWorld),
                               (r'/display', DisplayHandler),
                               (r'/static/(.+)', StaticFileHandler)
                              ], debug=True)

我的css文件位于app root下的文件夹中:/static/css/main.css

我可以通过直接网址访问该文件,甚至可以将其作为样式表链接,但这些样式不适用。有任何想法吗?还有另一种方式来提供样式表吗?有哪些方法可以实现类似于GAE的app.yaml?

3 个答案:

答案 0 :(得分:0)

你不需要静态文件处理程序 使用静态文件夹上传应用程序,方法是将其添加到app.yaml

- url: /static/
  static_dir: static

文档在这里:https://developers.google.com/appengine/docs/python/config/appconfig#Static_Directory_Handlers

编辑: 请参阅以下评论中的答案

答案 1 :(得分:0)

@Mnemon,请你解决我的问题。我会赞成你,但我不允许这样做。你说服我,如果它不是没有GAE的唯一webapp2方式,它至少是一种可行的方式。

但我也可以贡献你的解决方案现在可以安装为" pip install webapp2_static",来自pipi ---一位似乎正在使用他真名的作者......你我确定。我发现其他有用的webapp2文档here

我在Linux桌面开发服务器上使用粘贴实现您的代码,您也使用了它:

def main():
    from paste import httpserver
    httpserver.serve(app, host='127.0.0.1', port='8080')

但是使用上面的代码(看起来与webapp2_static.py文件完全相同),我发现将我的css文件放在app根目录中名为static的文件夹中正如你所说。

例如,我有/home/user/proj/public_html/app/app.py,其中py文件包含您的代码以及其他&#34; views&#34;对于我的超简单网站。 (我不知道粘贴是如何工作的,所以也许现在public_html就在那里供参考,以便在我将内容上传到生产服务器时不会感到困惑。)< / p>

因此,如果我将css样式表放入名为/ static的文件夹中,那么,如果我将/ static放入/ app或/ public_html的子目录中,我发现这两个位置都不起作用;我必须把它变成/ proj的子目录。

我并不期待这一点,但对我而言,治愈方法是改变默认的静态&#39;在你的app.configure.get(...,&#39;静态&#39;)来电,到&#39; public_html / app / static&#39;。然后它可以使用/ app。中的/ static文件夹。

同样地使用带有&#39; ./ app / static /的pipi代码代替默认的&#39;静态&#39;没有工作;我发现我需要./public_html/app/static(或者它可能只是/ public_html / app / static甚至是public_html / app / static ......我忘了......其中一个有效)。

我测试了你的abs_path计算是如何工作的,并在下面的代码中对其进行了重新设计,其中我将你的方法简化为更多Djangoesque。也就是说,在我的一个应用程序py文件中,我把顶部放在下面:

STATIC_DIR = os.sep + 'tostatic' + os.path.abspath(os.path.dirname(__file__)) + os.sep + 'static'

然后在我想要添加css的页面中,我的主页在我的情况下,我把它变得非常可读:

<link href="{{STATIC_DIR}}/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">

对于&#34;视图&#34;生成我的主页(env是一个以模板加载器为参数的jinja2 Environment对象):

class Home(webapp2.RequestHandler):
    def get(self):
        template = env.get_template('index.html')
        template_values = {'STATIC_DIR': STATIC_DIR }
        self.response.write(template.render(template_values))

最后,URL路由如下:

app = webapp2.WSGIApplication(
[
(r'/', Home),
(r'/tostatic/(.+)', StaticView),
], debug=True)

现在提供静态文件的视图:

class StaticView(webapp2.RequestHandler):
    def get(self, path):
        path = os.sep + path
        try:
            f = open(path, 'r')
            self.response.headers.add_header('Content-Type', mimetypes.guess_type(path)[0])
            self.response.out.write(f.read())
            f.close()
        except Exception, e:
            print 'Problem in StaticView:', e
            self.response.set_status(404)

最后关闭,我对你的方法所遇到的问题是我和其他近乎新手的问题,即URL与文件系统的遗留关联的偏离。在你的方法&#34;静态&#34;是一个子目录和URL前面的斜杠之间的字符串,它告诉解释器运行哪个视图(哪个webapp2.RequestHandler子类)。您从URL的其余部分获取/ static,然后再对其进行硬编码。当需要决定在标记中放入href的内容时,HTML页面编码器必须记住这种双重性。使用{{STATIC_DIR}}模板变量方法,可以清楚地了解该怎么做。并且很容易重新定义静态文件的位置 - 只需要更改STATIC_DIR声明。

我发现self.response.set_status(404)显示在Firebug中,但不是Firefox。显然,使用webapp2,您必须提供并提供自己的HTTP状态代码页。

答案 2 :(得分:0)

self.response.headers.add_header('Content-Type', mimetypes.guess_type(abs_path)[0])
self.response.headers['Content-Type'] = mimetypes.guess_type(abs_path)[0]