Flask'taki statik dosyalar - robot.txt, sitemap.xml (mod_wsgi)


94

Statik dosyaları Flask'ın uygulama kök dizininde depolamak için akıllıca bir çözüm var mı? robots.txt ve sitemap.xml'nin / içinde bulunması bekleniyor, bu yüzden benim fikrim onlar için yollar oluşturmaktı:

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

Daha uygun bir şey olmalı :)

Yanıtlar:


78

En iyi yol, static_url_path'i kök url'ye ayarlamaktır

from flask import Flask

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

Static_folder'ın proje klasöründe olması gerekmediğini belirtmekte fayda var. örneğin static_folder = '/ app / ui' iyidir.
ashic

66

@vonPetrushev haklı, üretimde statik dosyaları nginx veya apache aracılığıyla sunmak isteyeceksiniz, ancak geliştirme için, geliştirme ortamınızın python uygulamanızın statik içeriğe hizmet etmesini sağlamak, böylece endişelenmenize gerek kalmaması güzel. konfigürasyonları ve birden çok projeyi değiştirmek hakkında. Bunu yapmak için, SharedDataMiddleware'i kullanmak isteyeceksiniz .

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')
    })

Bu örnek, statik dosyalarınızın "statik" klasöründe olduğunu varsayar, ortamınıza uygun olanı ayarlayın.


1
TEŞEKKÜRLER! İhtiyacım olan şey bu! Bunu üretim heroku için yapmak istiyorum. Aşağıdaki başlıktaki yanıtlara bakın: flask.pocoo.org/mailinglist/archive/2012/2/22/…
David

2
Dikkat - bunu halletmenin daha kolay bir yolu var. Cevabımı kontrol edin.
Sean McSomething

1
SharedDataMiddleware'in yalnızca '/' öğesini index.html veya benzerine çözümlemesinin bir yolu var mı?
gromgull

64

Bu sorunun en temiz yanıtı, bu (aynı) sorunun cevabıdır :

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

Özetlemek:

  • David'in belirttiği gibi, doğru yapılandırmayla üretim yoluyla birkaç statik dosya sunmanın
  • /robots.txt dosyasının aranması /static/robots.txt dosyasına yönlendirmeye neden olmamalıdır. (Seans'ın yanıtında bunun nasıl başarıldığı hemen belli değil.)
  • Statik dosyaları uygulamanın kök klasörüne eklemek temiz değil
  • son olarak, önerilen çözüm ara yazılım ekleme yaklaşımından çok daha temiz görünüyor:

Veya bir plan kullanıyorsanız, @bp.route(...)ve sonra kullanabilirsiniz current_app.static_folder. (Şişeden içe aktar current_app, aynı requestvesend_from_directory
Sean McCarthy

23

Bu eski bir cevaplanmış soru olmasına rağmen, bunu cevaplıyorum çünkü bu yazı Google sonuçlarında oldukça yüksek çıkıyor. Belgelerde ele alınmasa da, Flask Uygulaması nesne yapıcısı için API belgelerini okursanız , kapsanır. Adlandırılmış parametreyi static_folderşu şekilde ileterek :

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

... statik dosyaların nereden sunulacağını tanımlayabilirsiniz. Benzer şekilde, sizin template_folderadınızı da tanımlayabilirsiniz static_url_path.


@chmike evet, varsayılan değerdir, /staticancak bunu geçersiz kılarak değiştirebilirsiniz static_url_path.
Sean McSomething

Bu doğru ama diğer cevaplar daha esnektir. Bu, yalnızca bir dizin yoluna hizmet verebileceği gerçeğiyle sınırlıdır.
Thomas Dignan

Bu, orijinal sorunun cevabı değil.
Paolo Casciello

2
Static_url_path değerini "" olarak ayarlarsanız, dosyaları / konumundan sunabilirsiniz.
Beau

Bu, Flask'ı statik dosyalar sunmaya zorlar. Ya nginx veya apache'nin onlara hizmet etmesini istiyorsanız?
Markon

15

Statik dosyaların sunulmasının, dinamik içerik sunmayı amaçlayan uygulamayla hiçbir ilgisi yoktur. Statik dosyaları sunmanın doğru yolu, kullandığınız sunucuya bağlıdır. Sonuçta, uygulamanızı çalışır hale getirdiğinizde, onu bir web sunucusuna bağlamanız gerekecek. Sadece apache httpd için konuşabiliyorum, bu nedenle statik dosyaların sunulma şekli, uygulamanıza mod-wsgi aracılığıyla bağladığınız sanal konakta tanımlanır. Site haritalarını, robots.txt dosyasını veya herhangi bir statik içeriği nasıl sunacağınızı gösterecek kılavuz: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site


Aradığım cevap bu. Teşekkürler!
biesiad

1
Bir uygulama, bazıları dinamik ve bazıları statik içerik sunmak içindir.
Dem Pilafian

14

Statik dosya göndermenin başka bir yolu da şuna benzer bir tümünü yakalama kuralı kullanmaktır:

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

Bunu, geliştirme sırasında kurulumu en aza indirgemek için kullanıyorum. Fikri http://flask.pocoo.org/snippets/57/ adresinden aldım

Ayrıca, bağımsız makinemde flask kullanarak geliştiriyorum, ancak üretim sunucusunda Apache ile konuşlandırıyorum. Kullanırım:

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
Dikkat - bunu halletmenin daha kolay bir yolu var. Cevabımı kontrol edin.
Sean McSomething

Birden fazla yol sunmanız gerekiyorsa mükemmel bir yol!
Thomas Dignan

6

Bu soru sorulduğundan beri eklenmiş olabilir, ancak flask'ın "helpers.py" kısmına bakıyordum ve flask.send_from_directory'yi buldum:

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'a başvuran:

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

... bu, daha fazla denetim için daha iyi görünüyor, ancak send_from_directory ** seçenekleri doğrudan send_file'a aktarıyor.


3

Buradaki belgelerden: http://flask.pocoo.org/docs/quickstart/#static-files

Dinamik web uygulamaları da statik dosyalara ihtiyaç duyar. Bu genellikle CSS ve JavaScript dosyalarının geldiği yerdir. İdeal olarak web sunucunuz size hizmet edecek şekilde yapılandırılmıştır, ancak geliştirme sırasında Flask da bunu yapabilir. Paketinizde veya modülünüzün yanında statik adlı bir klasör oluşturun ve bu, uygulamada / static konumunda bulunacaktır.

URL'nin bu kısmına URL'ler oluşturmak için özel 'statik' URL adını kullanın:

url_for ('statik', dosya adı = 'stil.css')

Dosya, dosya sisteminde statik / style.css olarak depolanmalıdır.


0

Ben de aynı ikilemi yaşıyorum. Bazıları aradı ve cevabımı buldu (MHO):

Belgelerden de alıntı yapılabilir

Dinamik web uygulamaları da statik dosyalara ihtiyaç duyar. Bu genellikle CSS ve JavaScript dosyalarının geldiği yerdir. İdeal olarak, web sunucunuz size hizmet edecek şekilde yapılandırılmıştır, ancak geliştirme sırasında Flask da bunu yapabilir . Paketinizde veya modülünüzün yanında statik adlı bir klasör oluşturun ve bu, uygulamada / static konumunda mevcut olacaktır.

IMHO: Uygulamanız üretime hazır olduğunda , statik dosya sunumu web sunucusunda (nginx, apache) yapılandırılmalıdır (veya ideal olarak); ancak geliştirme sırasında Flask, statik dosyaları sunmak için onu kullanılabilir hale getirdi. Bu, hızlı bir şekilde gelişmenize yardımcı olmak içindir - web sunucusu vb.

Umarım yardımcı olur.


0

Bunu dene:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.