Flask static_folder размещен на S3

Я пытаюсь перенаправить весь мой /статический контент на Amazon S3. Моей первой мыслью было использовать глобальную конфигурацию ['path'] во всех моих шаблонах jinja, но это не сработает для внешних файлов css и js, к тому же это довольно беспорядочно. Я нашел static_folder и static_url_path, выпущенные в 0.7, и это похоже на то, что я хочу. Однако, когда я перехожу к http://localhost:8000/static/img/abc.jpg он не находит файлы на S3. Правильно ли я использую эту функцию или есть другой способ сделать это?

Спасибо!


person Tim    schedule 25.02.2012    source источник


Ответы (5)


Недавно я разработал расширение Flask именно для этой ситуации. Он называется Flask-S3, и вы можете прочитать документацию по нему здесь.

В качестве примера, вот как вы можете интегрировать его в свое приложение 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 распознает схемы и загружает все ресурсы, связанные с любыми зарегистрированными схемами.

person Edwardr    schedule 28.10.2012

Я бы хотел, чтобы аргумент static_url_path конструктора flask.Flask принимал полный URI, но он кричит о том, что путь требует косой черты, когда вы пытаетесь это сделать. Если бы он принял это, вы могли бы просто использовать url_for после установки static_url_path='http://my_s3_bucket.aws.amazon.com/' или около того.

Другим возможным решением является использование процессора контекста. Я считаю, что это самое чистое решение, но у меня нет большого опыта работы с флягой. Он действительно выглядит чистым. Используя процессор контекста, я извлекаю 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" />
person Colin Dunklau    schedule 21.09.2012

Я знаю, что это старый вопрос, но вот как я могу обойти эту проблему.

  • Импортируйте метод url_for Flask под другим именем (например, flask_url_for)
  • Создайте свой собственный настраиваемый метод url_for, который вызывает flask_url_for, а затем использует замену строки для добавления в URL-адрес корзины S3.

Мне нравится эта стратегия, потому что она проста и интуитивно понятна в использовании, а интерфейс точно такой же, как у исходного метода 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
person Carolyn Conway    schedule 26.06.2016

то, что вы пытаетесь сделать, это иметь возможность писать

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

и есть ли это решение для URL-адреса в s3?

я считаю, что 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 в файловой системе.

я думаю, что вы хотите сделать, это потенциально написать собственный фильтр, который переведет ваш путь в URL-адрес s3, чтобы вы могли сделать вызов что-то вроде

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

здесь есть некоторая документация по этому поводу: пользовательские фильтры flask

person David    schedule 02.08.2012

Вам нужен URL общедоступного файла Amazon S3 вместо 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 %}

Это даст вам путь по умолчанию, когда вы можете тестировать свое приложение локально, и общедоступный URL-адрес S3, когда он находится в производстве (на основе флага отладки).

Используй это:

<script src="{{ STATIC_ROOT }}js/jquery.min.js">

person Sharoon Thomas    schedule 02.08.2012
comment
Некрасиво, не надо. Просто используйте процессор контекста, чтобы установить переменную. - person Colin Dunklau; 22.09.2012