File statis di Flask - robot.txt, sitemap.xml (mod_wsgi)

94

Apakah ada solusi cerdas untuk menyimpan file statis di direktori root aplikasi Flask. robots.txt dan sitemap.xml diharapkan ada di /, jadi ide saya adalah membuat rute untuk mereka:

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

Pasti ada sesuatu yang lebih nyaman :)

biesiad
sumber

Jawaban:

78

Cara terbaik adalah menyetel static_url_path ke root url

from flask import Flask

app = Flask(__name__, static_folder='static', static_url_path='')
dns
sumber
Perlu disebutkan bahwa static_folder tidak harus ada di folder proyek. misalnya static_folder = '/ app / ui' baik-baik saja.
ashic
66

@vonPetrushev benar, dalam produksi Anda ingin menyajikan file statis melalui nginx atau apache, tetapi untuk pengembangan, senang memiliki lingkungan dev Anda yang sederhana karena aplikasi python Anda juga menyajikan konten statis sehingga Anda tidak perlu khawatir tentang mengubah konfigurasi dan beberapa proyek. Untuk melakukan itu, Anda harus menggunakan 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')
    })

Contoh ini mengasumsikan file statis Anda berada di folder "statis", sesuaikan dengan apa pun yang sesuai dengan lingkungan Anda.

Philip Southam
sumber
1
TERIMA KASIH! Inilah yang saya butuhkan! Saya ingin melakukan ini untuk heroku produksi saya. Lihat jawaban di utas berikut: flask.pocoo.org/mailinglist/archive/2012/2/22/…
David
2
Perhatian - ada cara yang lebih mudah untuk menangani ini sekarang. Periksa balasan saya.
Sean McSomething
1
Apakah ada cara bagi SharedDataMiddleware untuk menyelesaikan hanya '/' ke index.html atau serupa?
gromgull
63

Jawaban terbersih untuk pertanyaan ini adalah jawaban untuk ini (identik) pertanyaan :

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:])

Untuk meringkas:

  • seperti yang ditunjukkan David, dengan konfigurasi yang tepat tidak apa - apa untuk menyajikan beberapa file statis melalui prod
  • mencari /robots.txt seharusnya tidak mengarah ke /static/robots.txt. (Dalam jawaban Seans, tidak segera jelas bagaimana itu dicapai.)
  • tidak bersih menambahkan file statis ke folder root aplikasi
  • akhirnya, solusi yang diusulkan terlihat jauh lebih bersih daripada menambahkan pendekatan middleware:
bebbi
sumber
23

Meskipun ini adalah pertanyaan terjawab lama, saya menjawab ini karena posting ini muncul cukup tinggi di hasil Google. Meskipun tidak tercakup dalam dokumentasi, jika Anda membaca dokumen API untuk konstruktor objek Aplikasi Flask, hal itu akan tercakup. Dengan melewatkan parameter bernama static_folderseperti ini:

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

... Anda dapat menentukan dari mana file statis disajikan. Demikian pula, Anda dapat menentukan a template_folder, nama Anda static_url_path.

Sean McSomething
sumber
@chmike ya, defaultnya /statictapi Anda bisa mengubahnya dengan menimpa static_url_path.
Sean McSomething
Ini benar tetapi jawaban lain lebih fleksibel. Yang ini dibatasi oleh fakta bahwa ia hanya dapat melayani satu jalur direktori.
Thomas Dignan
Ini bukanlah jawaban dari pertanyaan awal.
Paolo Casciello
2
Jika Anda menyetel static_url_path ke "" Anda dapat menyediakan file dari /.
Indah
Ini memaksa Flask untuk menyajikan file statis. Bagaimana jika Anda ingin nginx atau apache melayani mereka?
Markon
15

Melayani file statis tidak ada hubungannya dengan aplikasi yang dimaksudkan untuk mengirimkan konten dinamis. Cara yang benar untuk menyajikan file statis bergantung pada server yang Anda gunakan. Lagi pula, saat Anda mengaktifkan dan menjalankan aplikasi, Anda harus mengikatnya ke server web. Saya hanya dapat berbicara untuk httpd apache, jadi cara melayani file statis ditentukan dalam host virtual yang Anda ikat ke aplikasi Anda melalui mod-wsgi. Berikut adalah panduan yang akan menunjukkan kepada Anda cara menyajikan peta situs, robots.txt atau konten statis lainnya: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site

vonPetrushev
sumber
Itulah jawaban yang selama ini saya cari. Terima kasih!
biesiad
1
Aplikasi dimaksudkan untuk mengirimkan konten, sebagian dinamis dan sebagian statis.
Dem Pilafian
14

Cara lain untuk mengirim file statis adalah dengan menggunakan aturan penampung-semua seperti ini:

@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()

Saya menggunakan ini untuk mencoba meminimalkan pengaturan saat mengembangkan. Saya mendapat ide dari http://flask.pocoo.org/snippets/57/

Selanjutnya, saya mengembangkan menggunakan flask di mesin mandiri saya tetapi menerapkan dengan Apache di server produksi. Saya menggunakan:

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()
Ben Golding
sumber
1
Perhatian - ada cara yang lebih mudah untuk menangani ini sekarang. Periksa balasan saya.
Sean McSomething
Cara terbaik jika Anda perlu melayani banyak jalur!
Thomas Dignan
6

Ini mungkin telah ditambahkan sejak pertanyaan ini ditanyakan, tetapi saya sedang melihat-lihat "helpers.py" flask dan saya menemukan 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.
'''

... yang mereferensikan flask.send_file:

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

... yang tampaknya lebih baik untuk kontrol lebih, meskipun send_from_directory meneruskan ** opsi langsung ke send_file.

blast_hardcheese
sumber
3

Dari dokumentasi di sini: http://flask.pocoo.org/docs/quickstart/#static-files

Aplikasi web dinamis juga membutuhkan file statis. Biasanya dari situlah file CSS dan JavaScript berasal. Idealnya server web Anda dikonfigurasi untuk menyajikannya untuk Anda, tetapi selama pengembangan Flask juga dapat melakukannya. Cukup buat folder bernama statis dalam paket Anda atau di sebelah modul Anda dan itu akan tersedia di / static pada aplikasi.

Untuk membuat URL ke bagian URL tersebut, gunakan nama URL 'statis' khusus:

url_for ('statis', namafile = 'style.css')

File harus disimpan di sistem file sebagai static / style.css.

Josh Klein
sumber
0

Saya juga mengalami dilema yang sama. Melakukan pencarian dan menemukan jawaban saya (MHO):

Sekalian mengutip dari dokumentasi

Aplikasi web dinamis juga membutuhkan file statis. Biasanya dari situlah file CSS dan JavaScript berasal. Idealnya server web Anda dikonfigurasi untuk menyajikannya untuk Anda, tetapi selama pengembangan Flask juga dapat melakukannya . Buat saja folder bernama static dalam paket Anda atau di sebelah modul Anda dan itu akan tersedia di / static pada aplikasi.

IMHO: Saat aplikasi Anda siap untuk diproduksi , penayangan file statis harus (atau idealnya) dikonfigurasi di server web (nginx, apache); tetapi selama pengembangan , Flask membuatnya tersedia untuk menyajikan file statis. Ini untuk membantu Anda berkembang pesat - tidak perlu mengatur server web dan semacamnya.

Semoga membantu.

jpanganiban
sumber
0

Coba ini:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Farzad Amirjavid
sumber