【问题标题】:Flask static_folder hosted on S3Flask static_folder 托管在 S3 上
【发布时间】:2012-02-25 04:58:45
【问题描述】:

我正在尝试将我的所有 /static 内容重新路由到 Amazon S3 上的主机。我的第一个想法是在我的 jinja 模板中使用 global config['path'] ,但这不适用于外部 css 和 js 文件,而且有点混乱。我找到了 0.7 中发布的 static_folder 和 static_url_path,这似乎是我想要的。但是,当我转到 http://localhost:8000/static/img/abc.jpg 时,它不会在 S3 上找到文件。我是否正确使用了此功能,还是有其他方法可以做到这一点?

谢谢!

【问题讨论】:

    标签: python amazon-s3 flask jinja2


    【解决方案1】:

    我最近开发了一个 Flask 扩展来处理这种情况。它被称为Flask-S3,你可以阅读它的文档here

    例如,以下是您将其集成到 Flask 应用程序中的方法:

    from flask import Flask
    from flask_s3 import FlaskS3
    
    app = Flask(__name__)
    app.config['S3_BUCKET_NAME'] = 'mybucketname'
    s3 = FlaskS3(app)
    

    您可以使用扩展程序将您的资产上传到您选择的存储桶:

    >>> from my_application import app
    >>> from flask_s3 import create_all
    >>> create_all(app)
    

    Flask-S3 可识别蓝图,并将上传与任何注册蓝图相关的所有资产。

    【讨论】:

      【解决方案2】:

      我希望 flask.Flask 构造函数的 static_url_path 参数能够接受完整的 URI,但是当您尝试这样做时,它会尖叫路径需要前导斜杠。如果它接受它,你可以在设置static_url_path='http://my_s3_bucket.aws.amazon.com/'左右之后使用url_for

      另一种可能的解决方案是使用上下文处理器。我相信这是最干净的解决方案,但我对烧瓶没有太多经验。它确实看起来干净。使用上下文处理器,我从环境中提取 URL(我正在使用 heroku,所以它很容易设置)。然后上下文处理器使 static_url 变量在我的模板中可用。

      在 app.py 中:

      # Environment has STATIC_URL='http://my_s3_bucket.aws.amazon.com/'
      @app.context_processor
      def inject_static_url():
          """
          Inject the variable 'static_url' into the templates. Grab it from
          the environment variable STATIC_URL, or use the default.
      
          Template variable will always have a trailing slash.
      
          """
          static_url = os.environ.get('STATIC_URL', app.static_url_path)
          if not static_url.endswith('/'):
              static_url += '/'
          return dict(
              static_url=static_url
          )
      

      在模板中:

      <link rel="stylesheet" type="text/css" href="{{ static_url }}css/main.css" />
      

      结果

      <link rel="stylesheet" type="text/css" href="http://my_s3_bucket.aws.amazon.com/css/main.css" />
      

      【讨论】:

        【解决方案3】:

        我知道这是一个老问题,但这是我解决这个问题的方法。

        • 以不同的名称导入 Flask 的 url_for 方法(例如,flask_url_for
        • 创建您自己的自定义 url_for 方法,该方法调用flask_url_for,然后使用字符串替换添加到您的 S3 存储桶 url。

        我喜欢这个策略,因为它使用起来简单直观,界面和原来的url_for方法一模一样。

        from flask import url_for as flask_url_for
        from flask import current_app
        
        PRODUCTION_URL = 'https://s3.amazonaws.com/MY-BUCKET-NAME'
        
        def url_for(path, **kwargs):
            url = flask_url_for(path, **kwargs)
            if url.startswith("/static") and not current_app.debug:
                url = url.replace("/static", "", 1)
                return PRODUCTION_URL + url
            return url
        

        【讨论】:

          【解决方案4】:

          你想要完成的是能够写作

          {{ url_for(app.static, file='img/abc.jpg', _external=True) }}

          并将该解析为 s3 中的 url?

          我相信 static_folder 和 static_url_path 是设置好的,所以如果你调用

          app = Application('app', static_folder='foo', static_url_path='bar')

          然后去

          上面的 url_for 会输出

          http://localhost:8000/bar/img/abc.jpg,它会在文件系统中寻找static/img/abc.jpg

          我认为您想要做的可能是编写一个自定义过滤器,将您的路径转换为 ​​s3 url,以便您可以拨打类似的电话

          {{ 'img/abc.jpg'|s3_static_url }}

          这里有一些文档:flask custom filters

          【讨论】:

            【解决方案5】:

            您需要的是 Amazon S3 公共文件 URL,而不是 http://localhost:8000/static/img/abc.jpg。如果它只是几个文件,可以使用完整的 URL 将它们硬编码到您的模板中,或者如果您将有一个本地版本进行测试并在生产站点上使用 S3(就像我们一样),那么您可以尝试以下方法。

            在基本模板(其他模板继承)的顶部定义一个可能称为 STATIC_ROOT 的新变量,并将其用作文件路径前缀。

            例如:

            {% if app.debug %}
                {% set  STATIC_ROOT = url_for('static', filename='') %}
            {% else %}
                {% set STATIC_ROOT = 'http://s3.amazonaws.com/bucketname/' }
            {% endif %}
            

            当您可能在本地测试应用程序时,这将为您提供默认路径,并在生产时为您提供公共 S3 url(基于调试标志)。

            使用它:

            &lt;script src="{{ STATIC_ROOT }}js/jquery.min.js"&gt;

            【讨论】:

            • 丑,没必要。只需使用上下文处理器来设置变量。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-10-02
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多