Pliki statyczne we Flask - robot.txt, sitemap.xml (mod_wsgi)


94

Czy istnieje sprytne rozwiązanie do przechowywania plików statycznych w katalogu głównym aplikacji Flask? Pliki robots.txt i sitemap.xml powinny znajdować się w /, więc moim pomysłem było utworzenie dla nich tras:

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

Musi być coś wygodniejszego :)

Odpowiedzi:


78

Najlepszym sposobem jest ustawienie static_url_path na główny adres URL

from flask import Flask

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

Warto wspomnieć, że static_folder nie musi znajdować się w folderze projektu. np. static_folder = „/ app / ui” jest w porządku.
— ashic

66

@vonPetrushev ma rację, w produkcji będziesz chciał obsługiwać pliki statyczne przez nginx lub apache, ale w przypadku programowania dobrze jest mieć proste środowisko programistyczne, w którym aplikacja Python obsługuje również statyczną zawartość, więc nie musisz się martwić o zmianie konfiguracji i wielu projektach. Aby to zrobić, będziesz chciał użyć 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')
    })

Ten przykład zakłada, że ​​Twoje pliki statyczne znajdują się w folderze „static”, dostosuj je do tego, co pasuje do Twojego środowiska.


1
DZIĘKI! To jest to, czego potrzebowałem! Chcę to zrobić dla mojego heroku produkcyjnego. Zobacz odpowiedzi w następującym wątku: flask.pocoo.org/mailinglist/archive/2012/2/22/…
— David

2
Uwaga - teraz jest łatwiejszy sposób, aby sobie z tym poradzić. Sprawdź moją odpowiedź.
— Sean McSomething,

1
Czy istnieje sposób, aby SharedDataMiddleware rozpoznał tylko „/” do pliku index.html lub podobnego?
— gromgull,

63

Najczystszą odpowiedzią na to pytanie jest odpowiedź na to (identyczne) pytanie :

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

Podsumowując:

  • jak zauważył David, z odpowiednią konfiguracją można obsłużyć kilka statycznych plików przez prod
  • szukanie /robots.txt nie powinno skutkować przekierowaniem do /static/robots.txt. (W odpowiedzi Seans nie jest od razu jasne, jak to się osiągnęło.)
  • dodawanie plików statycznych do folderu głównego aplikacji nie jest czyste
  • wreszcie, proponowane rozwiązanie wygląda na znacznie czystsze niż podejście polegające na dodawaniu oprogramowania pośredniego:

23

Mimo że jest to stare pytanie, odpowiadam na nie, ponieważ ten post pojawia się dość wysoko w wynikach Google. Chociaż nie jest to uwzględnione w dokumentacji, jeśli czytasz dokumentację API dla konstruktora obiektów Flask Application, jest to objęte. Przekazując nazwany parametr w ten static_foldersposób:

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

... możesz określić, skąd mają być obsługiwane pliki statyczne. Podobnie, możesz zdefiniować swoje template_folderimię static_url_path.


@chmike tak, domyślnie, /staticale możesz to zmienić, zastępując static_url_path.
— Sean McSomething

To prawda, ale inne odpowiedzi są bardziej elastyczne. Ten jest ograniczony przez fakt, że może obsługiwać tylko jedną ścieżkę katalogu.
— Thomas Dignan,

To nie jest odpowiedź na pierwotne pytanie.
— Paolo Casciello

2
Jeśli ustawisz static_url_path na „”, możesz udostępniać pliki z /.
— Beau,

Zmusza to Flask do obsługi plików statycznych. A co jeśli chcesz, aby serwował im Nginx lub Apache?
— Markon,

15

Obsługa plików statycznych nie ma nic wspólnego z aplikacją, która ma dostarczać dynamiczną zawartość. Prawidłowy sposób obsługi plików statycznych zależy od używanego serwera. W końcu po uruchomieniu i uruchomieniu aplikacji będziesz musiał powiązać ją z serwerem internetowym. Mogę mówić tylko o apache httpd, więc sposób obsługi plików statycznych jest zdefiniowany na hoście wirtualnym, który łączysz z aplikacją za pomocą mod-wsgi. Oto przewodnik, który pokaże Ci, jak udostępniać mapy witryn, plik robots.txt lub dowolną zawartość statyczną: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site


To odpowiedź, której szukałem. Dzięki!
— biesiad

1
Aplikacja ma dostarczać treść, część dynamiczną, a część statyczną.
— Dem Pilafian

14

Innym sposobem wysyłania plików statycznych jest użycie reguły catch-all, takiej jak ta:

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

Używam tego, aby zminimalizować konfigurację podczas programowania. Pomysł pochodzi z http://flask.pocoo.org/snippets/57/

Co więcej, pracuję przy użyciu Flask na mojej samodzielnej maszynie, ale wdrażam z Apache na serwerze produkcyjnym. Używam:

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
Uwaga - teraz jest łatwiejszy sposób, aby sobie z tym poradzić. Sprawdź moją odpowiedź.
— Sean McSomething

Doskonały sposób, jeśli musisz obsługiwać wiele ścieżek!
— Thomas Dignan,

6

Mogło to zostać dodane od czasu zadania tego pytania, ale przeglądałem plik „helpers.py” flask i znalazłem 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.
'''

... który odwołuje się do flask.send_file:

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

... co wydaje się lepsze dla większej kontroli, chociaż send_from_directory przekazuje ** opcje bezpośrednio do send_file.


3

Z dokumentacji tutaj: http://flask.pocoo.org/docs/quickstart/#static-files

Dynamiczne aplikacje internetowe również wymagają plików statycznych. Zwykle stamtąd pochodzą pliki CSS i JavaScript. W idealnym przypadku serwer WWW jest skonfigurowany tak, aby służył za Ciebie, ale Flask może to zrobić również podczas programowania. Po prostu utwórz folder o nazwie static w swoim pakiecie lub obok modułu, a będzie on dostępny w / static w aplikacji.

Aby wygenerować adresy URL do tej części adresu URL, użyj specjalnej „statycznej” nazwy adresu URL:

url_for ('statyczny', nazwa_pliku = 'style.css')

Plik musi być przechowywany w systemie plików jako static / style.css.


0

Ja też mam ten sam dylemat. Poszukałem i znalazłem odpowiedź (MHO):

Równie dobrze można cytować z dokumentacji

Dynamiczne aplikacje internetowe również wymagają plików statycznych. Zwykle stamtąd pochodzą pliki CSS i JavaScript. W idealnym przypadku serwer WWW jest skonfigurowany tak, aby służył za Ciebie, ale Flask może to zrobić również podczas programowania . Po prostu utwórz folder o nazwie static w swoim pakiecie lub obok modułu, a będzie on dostępny w / static w aplikacji.

IMHO: Gdy aplikacja jest gotowa do produkcji , statyczne serwowanie plików powinno być (lub jest idealnie) skonfigurowane na serwerze internetowym (nginx, apache); ale podczas rozwoju Flask udostępnił go do obsługi plików statycznych. Ma to pomóc w szybkim rozwoju - nie ma potrzeby konfigurowania serwerów WWW i tym podobnych.

Mam nadzieję, że to pomoże.


0

Spróbuj tego:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.