Флажок static_folder, размещенный на S3
Я пытаюсь перенаправить весь мой/статический контент для размещения на Amazon S3. Моя первая мысль заключалась в том, чтобы использовать глобальную конфигурацию ['path'] во всех моих шаблонах jinja, но это не будет работать для внешних файлов css и js, плюс это будет беспорядочно. Я обнаружил, что static_folder и static_url_path выпущены в 0.7, и это похоже на то, что я хочу. Однако, когда я перехожу в http://localhost:8000/static/img/abc.jpg, он не находит файлы на S3. Я правильно использую эту функцию или есть какой-то другой способ сделать это?
Спасибо!
Ответы
Ответ 1
Недавно я разработал расширение 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 информирует о проекте и загружает все активы, связанные с любыми зарегистрированными чертежами.
Ответ 2
Я бы хотел, чтобы конструктор flask.Flask
конструктор static_url_path
аргумент принял полный URI, но он кричит о пути, требующем ведущей косой черты, когда вы это пытаетесь. Если он примет это, вы можете просто использовать url_for
после установки static_url_path='http://my_s3_bucket.aws.amazon.com/'
или так.
Другим возможным решением является использование контекстного процессора. Я считаю, что это самое чистое решение, но у меня нет большого опыта в колбе. Это, конечно, выглядит чистым. Используя контекстный процессор, я вытаскиваю URL из среды (я использую героку, чтобы это было легко установить). Затем процессор контекста делает переменную 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
то, что вы пытаетесь выполнить, - это написать
{{ 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 }}
там есть документация по этому поводу: флажные пользовательские фильтры
Ответ 4
Вам нужен 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">
Ответ 5
Я знаю, что это старый вопрос, но вот как я обошел эту проблему.
- Метод импорта флагов
url_for
под другим именем (например, 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