Статические файлы во Flask - robot.txt, sitemap.xml (mod_wsgi)


94

Есть ли какое-нибудь умное решение для хранения статических файлов в корневом каталоге приложения Flask. Ожидается, что robots.txt и sitemap.xml находятся в /, поэтому я решил создать для них маршруты:

@app.route('/sitemap.xml', methods=['GET'])
def sitemap():
  response = make_response(open('sitemap.xml').read())
  response.headers["Content-type"] = "text/plain"
  return response

Должно быть что-то удобнее :)

Ответы:


78

Лучший способ - установить static_url_path в корневой URL

from flask import Flask

app = Flask(__name__, static_folder='static', static_url_path='')

Стоит отметить, что static_folder не обязательно должен находиться в папке проекта. например, static_folder = '/ app / ui' в порядке.
ashic

66

@vonPetrushev прав, в производстве вы захотите обслуживать статические файлы через nginx или apache, но для разработки хорошо, если ваша среда разработки проста, если ваше приложение python также обслуживает статический контент, поэтому вам не нужно беспокоиться об изменении конфигураций и нескольких проектов. Для этого вам нужно использовать SharedDataMiddleware .

from flask import Flask
app = Flask(__name__)
'''
Your app setup and code
'''
if app.config['DEBUG']:
    from werkzeug import SharedDataMiddleware
    import os
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
      '/': os.path.join(os.path.dirname(__file__), 'static')
    })

В этом примере предполагается, что ваши статические файлы находятся в папке «static», настройте все, что подходит для вашей среды.


1
БЛАГОДАРНОСТЬ! Это то, что мне было нужно! Я хочу сделать это для своего продакшн-героку. Смотрите ответы в следующей теме: flask.pocoo.org/mailinglist/archive/2012/2/22/…
David

2
Внимание - теперь есть более простой способ справиться с этим. Проверьте мой ответ.
Sean McSomething

1
Есть ли способ для SharedDataMiddleware разрешить просто '/' в index.html или аналогичный?
gromgull

63

Самый ясный ответ на этот вопрос - это ответ на этот (идентичный) вопрос :

from flask import Flask, request, send_from_directory
app = Flask(__name__, static_folder='static')    

@app.route('/robots.txt')
@app.route('/sitemap.xml')
def static_from_root():
    return send_from_directory(app.static_folder, request.path[1:])

Обобщить:

  • как указал Дэвид, с правильной конфигурацией нормально обслуживать несколько статических файлов через prod
  • поиск /robots.txt не должен приводить к перенаправлению на /static/robots.txt. (В ответе Шона не сразу понятно, как этого добиться.)
  • не чисто добавлять статические файлы в корневую папку приложения
  • наконец, предлагаемое решение выглядит намного чище, чем подход с добавлением промежуточного программного обеспечения:

23

Несмотря на то, что это старый вопрос, я отвечаю на него, потому что этот пост занимает довольно высокое место в результатах Google. Хотя это не рассматривается в документации, если вы читали документацию по API для конструктора объекта Flask Application, о котором он рассказал. Передав именованный параметр static_folderследующим образом:

from flask import Flask
app = Flask(__name__,
            static_folder="/path/to/static",
            template_folder="/path/to/templates")

... вы можете определить, откуда будут подаваться статические файлы. Точно так же вы можете определить свое template_folderимя static_url_path.


@chmike: да, по умолчанию, /staticно вы можете изменить это, переопределив static_url_path.
Sean McSomething

Это правильно, но другие ответы более гибкие. Этот ограничен тем, что он может обслуживать только один путь к каталогу.
Thomas Dignan

Это не ответ на исходный вопрос.
Паоло Кашиелло

2
Если вы установите static_url_path в "", вы можете обслуживать файлы из /.
Beau

Это заставляет Flask обслуживать статические файлы. Что, если вы хотите, чтобы их обслуживали nginx или apache?
Markon

15

Обслуживание статических файлов не имеет ничего общего с приложением, предназначенным для доставки динамического содержимого. Правильный способ обслуживания статических файлов зависит от того, какой сервер вы используете. В конце концов, когда вы запустите свое приложение, вам нужно будет привязать его к веб-серверу. Я могу говорить только о apache httpd, поэтому способ обслуживания статических файлов определяется на виртуальном хосте, который вы привязываете к своему приложению через mod-wsgi. Вот руководство, которое покажет вам, как обслуживать карты сайта, robots.txt или любой статический контент: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site


Это ответ, который я искал. Благодарность!
biesiad

1
Приложение предназначено для доставки контента, отчасти динамического, а отчасти статического.
Дем

14

Еще один способ отправки статических файлов - использовать такое универсальное правило:

@app.route('/<path:path>')
def catch_all(path):
    if not app.debug:
        flask.abort(404)
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    return f.read()

Я использую это, чтобы попытаться минимизировать настройку при разработке. Я получил идею от http://flask.pocoo.org/snippets/57/

Кроме того, я разрабатываю с использованием Flask на моем автономном компьютере, но развертываю с Apache на рабочем сервере. Я использую:

file_suffix_to_mimetype = {
    '.css': 'text/css',
    '.jpg': 'image/jpeg',
    '.html': 'text/html',
    '.ico': 'image/x-icon',
    '.png': 'image/png',
    '.js': 'application/javascript'
}
def static_file(path):
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    root, ext = os.path.splitext(path)
    if ext in file_suffix_to_mimetype:
        return flask.Response(f.read(), mimetype=file_suffix_to_mimetype[ext])
    return f.read()

[...]

if __name__ == '__main__':
    parser = optparse.OptionParser()
    parser.add_option('-d', '--debug', dest='debug', default=False,
                      help='turn on Flask debugging', action='store_true')

    options, args = parser.parse_args()

    if options.debug:
        app.debug = True
        # set up flask to serve static content
        app.add_url_rule('/<path:path>', 'static_file', static_file)
    app.run()

1
Внимание - теперь есть более простой способ справиться с этим. Проверьте мой ответ.
Sean McSomething

Отличный способ, если вам нужно обслуживать несколько путей!
Thomas Dignan

6

Это могло быть добавлено с тех пор, как был задан этот вопрос, но я просматривал flask "helpers.py" и нашел flask.send_from_directory:

send_from_directory(directory, filename, **options)
'''
  send_from_directory(directory, filename, **options)
  Send a file from a given directory with send_file.  This
  is a secure way to quickly expose static files from an upload folder
  or something similar.
'''

... который ссылается на flask.send_file:

send_file(filename_or_fp, mimetype=None, as_attachment=False, attachment_filename=None, add_etags=True, cache_timeout=43200, conditional=False)

... что кажется лучше для большего контроля, хотя send_from_directory передает ** параметры напрямую в send_file.


3

Из документации здесь: http://flask.pocoo.org/docs/quickstart/#static-files

Динамическим веб-приложениям также нужны статические файлы. Обычно отсюда берутся файлы CSS и JavaScript. В идеале ваш веб-сервер настроен для их обслуживания, но во время разработки Flask может это сделать. Просто создайте папку static в вашем пакете или рядом с вашим модулем, и она будет доступна в / static в приложении.

Чтобы сгенерировать URL-адреса для этой части URL-адреса, используйте специальное «статическое» имя URL:

url_for ('статический', имя файла = 'style.css')

Файл должен храниться в файловой системе как static / style.css.


0

У меня такая же дилемма. Провел поиск и нашел свой ответ (MHO):

Можно также процитировать из документации

Динамическим веб-приложениям также нужны статические файлы. Обычно отсюда берутся файлы CSS и JavaScript. В идеале ваш веб-сервер настроен для их обслуживания, но во время разработки Flask может это сделать . Просто создайте папку static в вашем пакете или рядом с вашим модулем, и она будет доступна в / static в приложении.

IMHO: когда ваше приложение готово к производству , обслуживание статических файлов должно быть (или в идеале) настроено на веб-сервере (nginx, apache); но во время разработки Flask сделал его доступным для обслуживания статических файлов. Это поможет вам быстро развиваться - не нужно настраивать веб-серверы и тому подобное.

Надеюсь, это поможет.


0

Попробуй это:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.