Статичні файли в 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/…
Девід

2
Зверніть увагу - зараз є простіший спосіб вирішити це. Перевірте мою відповідь.
Шон МакСомоті,

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. (У відповіді Seans не одразу ясно, як цього вдалося досягти.)
  • не чисто додавати статичні файли в кореневу папку програми
  • нарешті, пропоноване рішення виглядає набагато чистішим, ніж додавання підходу проміжного програмного забезпечення:

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.
Шон Максом щось

Це правильно, але інші відповіді є більш гнучкими. Цей обмежений тим фактом, що він може обслуговувати лише один шлях до каталогу.
Thomas Dignan

Це не відповідь на вихідне запитання.
Паоло Касчієлло,

2
Якщо ви встановите для static_url_path значення "", ви можете обслуговувати файли з /.
Beau,

Це змушує Flask обслуговувати статичні файли. Що робити, якщо ви хочете, щоб nginx або apache обслуговували їх?
Markon,

15

Обслуговування статичних файлів не має нічого спільного з програмою, яка призначена для доставки динамічного вмісту. Правильний спосіб обслуговування статичних файлів залежить від того, який сервер ви використовуєте. Зрештою, після запуску програми, її потрібно буде прив’язати до веб-сервера. Я можу говорити лише про apache httpd, тому спосіб обслуговування статичних файлів визначений у віртуальному хості, який ви прив'язуєте до своєї програми через mod-wsgi. Ось посібник, який покаже вам, як обслуговувати файли Sitemap, 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
Зверніть увагу - зараз є простіший спосіб вирішити це. Перевірте мою відповідь.
Шон МакСомоті,

Чудовий спосіб, якщо вам потрібно обслуговувати кілька шляхів!
Thomas Dignan

6

Це могло бути додано після того, як було задано це запитання, але я переглядав "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.