web-dev-qa-db-ja.com

Flaskで静的ファイルを提供する方法

だからこれは恥ずかしいです。私はFlaskで一緒に投げたアプリケーションを持っています、そして今のところそれはただCSSとJSへのいくつかのリンクで単一の静的なHTMLページを提供しています。そしてFlaskが静的ファイルを返すことを説明しているドキュメントのどこに私は見つけることができません。はい、render_templateを使用できますが、データはテンプレート化されていません。私はsend_fileまたはurl_forが正しいことだと思っていましたが、それらを機能させることができませんでした。それまでの間、私はファイルを開き、内容を読み、適切なMIMEタイプを持つResponseをリ​​ギングします。

import os.path

from flask import Flask, Response


app = Flask(__name__)
app.config.from_object(__name__)


def root_dir():  # pragma: no cover
    return os.path.abspath(os.path.dirname(__file__))


def get_file(filename):  # pragma: no cover
    try:
        src = os.path.join(root_dir(), filename)
        # Figure out how flask returns static files
        # Tried:
        # - render_template
        # - send_file
        # This should not be so non-obvious
        return open(src).read()
    except IOError as exc:
        return str(exc)


@app.route('/', methods=['GET'])
def metrics():  # pragma: no cover
    content = get_file('jenkins_analytics.html')
    return Response(content, mimetype="text/html")


@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def get_resource(path):  # pragma: no cover
    mimetypes = {
        ".css": "text/css",
        ".html": "text/html",
        ".js": "application/javascript",
    }
    complete_path = os.path.join(root_dir(), path)
    ext = os.path.splitext(path)[1]
    mimetype = mimetypes.get(ext, "text/html")
    content = get_file(complete_path)
    return Response(content, mimetype=mimetype)


if __== '__main__':  # pragma: no cover
    app.run(port=80)

誰かがこのためのコードサンプルやURLを与えたいですか?これは簡単なことではないだろうか。

378
hughdbrown

推奨される方法は、静的ファイルを処理するためにnginxまたは他のWebサーバーを使用することです。彼らはFlaskよりも効率的にそれを行うことができるでしょう。

ただし、ディレクトリからファイルを送信するには send_from_directory を使用できます。これは、状況によっては非常に便利です。

from flask import Flask, request, send_from_directory

# set the project root directory as the static folder, you can set others.
app = Flask(__name__, static_url_path='')

@app.route('/js/<path:path>')
def send_js(path):
    return send_from_directory('js', path)

if __== "__main__":
    app.run()

しない ユーザー指定のパスでsend_fileまたはsend_static_fileを使用します。

send_static_fileの例:

from flask import Flask, request
# set the project root directory as the static folder, you can set others.
app = Flask(__name__, static_url_path='')

@app.route('/')
def root():
    return app.send_static_file('index.html')
504
atupal

私はあなたがそこに必要なものを見つけると確信しています: http://flask.pocoo.org/docs/quickstart/#static-files

基本的にあなたは単にあなたのパッケージのルートに "static"フォルダを必要とし、そしてあなたはurl_for('static', filename='foo.bar')を使うか、 http://example.com/static/foo.bar であなたのファイルに直接リンクすることができます。

_ edit _ :コメントで示唆されているように、あなたは直接'/static/foo.bar' URLパス _を使うことができますが、_ url_for()オーバーヘッド(パフォーマンスに関して)はかなり低く、それを使うことを意味しますその後、動作を簡単にカスタマイズできるようになります(フォルダの変更、URLパスの変更、静的ファイルのS3への移動など)。

73
b4stien

あなたもできます、そしてこれは私のお気に入りです、中のファイルが皆のために到達可能であるように静的なパスとしてフォルダーを設定します。

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

そのセットで標準のHTMLを使うことができます:

<link rel="stylesheet" type="text/css" href="/static/style.css">
67
sharpshadow

静的ファイルの場所を移動するだけの場合は、最も簡単な方法はコンストラクタでパスを宣言することです。以下の例では、テンプレートと静的ファイルをwebというサブフォルダーに移動しました。

app = Flask(__name__,
            static_url_path='', 
            static_folder='web/static',
            template_folder='web/templates')
  • static_url_path=''はURLから先行するパスを削除します(デフォルトの/static)。
  • static_folder='web/static'はFlaskにweb/staticにあるファイルを提供するよう指示します。
  • template_folder='web/templates'、同様に、これはテンプレートフォルダを変更します。

このメソッドを使用すると、次のURLはCSSファイルを返します。

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">

そして最後に、これはフォルダ構造のスナップです。ここで、flask_server.pyはFlaskインスタンスです。

Nested Static Flask Folders

42
Richard Dunn

あなたはこの機能を使用することができます:

send_static_file(filename)
静的ファイルを静的フォルダからブラウザに送信するために内部的に使用される機能。

app = Flask(__name__)
@app.route('/<path:path>')
def static_file(path):
    return app.send_static_file(path)
35
BlackMamba

私が使っているのは(そしてそれは素晴らしい仕事をしていましたが) "templates"ディレクトリと "static"ディレクトリです。私はすべての.htmlファイル/ Flaskテンプレートをtemplatesディレクトリの中に置き、staticはCSS/JSを含みます。 Flaskのテンプレート構文をどの程度使用したかにかかわらず、render_templateは私の知る限りでは一般的なhtmlファイルに対してはうまく機能します。下記は私のviews.pyファイルのサンプル呼び出しです。

@app.route('/projects')
def projects():
    return render_template("projects.html", title = 'Projects')

別の静的ディレクトリで静的ファイルを参照したい場合は、必ずurl_for()を使用してください。あなたはたぶんHTMLのあなたのCSS/JSファイルリンクの中でとにかくこれをすることになるでしょう。例えば...

<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>

これが「標準的な」非公式のFlaskチュートリアルへのリンクです。

http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

33
Kyle Sum

他の答えに基づいた最も簡単な作業例は次のとおりです。

from flask import Flask, request
app = Flask(__name__, static_url_path='')

@app.route('/index/')
def root():
    return app.send_static_file('index.html')

if __== '__main__':
  app.run(debug=True)

index.html というHTMLで

<!DOCTYPE html>
<html>
<head>
    <title>Hello World!</title>
</head>
<body>
    <div>
         <p>
            This is a test.
         </p>
    </div>
</body>
</html>

重要: And index.html static というフォルダにあります。つまり、<projectpath>には.pyファイルがあり、<projectpath>\staticにはhtmlファイルがあります。

サーバーをネットワーク上で見えるようにしたい場合は、app.run(debug=True, Host='0.0.0.0')を使用してください。

編集: 要求された場合、フォルダ内のすべてのファイルを表示するには、これを使用してください。

@app.route('/<path:path>')
def static_file(path):
    return app.send_static_file(path)

これは本質的にBlackMambaの答えなので、彼らに賛成投票をしてください。

33
EpicPandaForce

次のフォルダツリーを作成するAngular + Boilerplateフローの場合:

backend/
|
|------ui/
|      |------------------build/          <--'static' folder, constructed by Grunt
|      |--<proj           |----vendors/   <-- angular.js and others here
|      |--     folders>   |----src/       <-- your js
|                         |----index.html <-- your SPA entrypoint 
|------<proj
|------     folders>
|
|------view.py  <-- Flask app here

私は以下の解決策を使用します。

...
root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui", "build")

@app.route('/<path:path>', methods=['GET'])
def static_proxy(path):
    return send_from_directory(root, path)


@app.route('/', methods=['GET'])
def redirect_to_index():
    return send_from_directory(root, 'index.html')
...

「静的」フォルダをカスタムに再定義するのに役立ちます。

7
user1671599

だから私は(@ user1671599の回答に基づいて)動いているものを手に入れたし、皆さんと共有したいと思いました。

(私はそれがPythonで私の最初のアプリだから私はそれが正しくやっていると思います)

これは私がしました -

プロジェクト構造:

enter image description here

server.py:

from server.AppStarter import AppStarter
import os

static_folder_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "client")

app = AppStarter()
app.register_routes_to_resources(static_folder_root)
app.run(__name__)

AppStarter.py:

from flask import Flask, send_from_directory
from flask_restful import Api, Resource
from server.ApiResources.TodoList import TodoList
from server.ApiResources.Todo import Todo


class AppStarter(Resource):
    def __init__(self):
        self._static_files_root_folder_path = ''  # Default is current folder
        self._app = Flask(__name__)  # , static_folder='client', static_url_path='')
        self._api = Api(self._app)

    def _register_static_server(self, static_files_root_folder_path):
        self._static_files_root_folder_path = static_files_root_folder_path
        self._app.add_url_rule('/<path:file_relative_path_to_root>', 'serve_page', self._serve_page, methods=['GET'])
        self._app.add_url_rule('/', 'index', self._goto_index, methods=['GET'])

    def register_routes_to_resources(self, static_files_root_folder_path):

        self._register_static_server(static_files_root_folder_path)
        self._api.add_resource(TodoList, '/todos')
        self._api.add_resource(Todo, '/todos/<todo_id>')

    def _goto_index(self):
        return self._serve_page("index.html")

    def _serve_page(self, file_relative_path_to_root):
        return send_from_directory(self._static_files_root_folder_path, file_relative_path_to_root)

    def run(self, module_name):
        if module_name == '__main__':
            self._app.run(debug=True)
6
danfromisrael
from flask import redirect, url_for
...
@app.route('/', methods=['GET'])
def metrics():
    return redirect(url_for('static', filename='jenkins_analytics.html'))

これはあなたのhtmlファイルで参照されるすべてのファイル(css&js ...)を処理します。

2
forzagreen

共有の考え....この例。

from flask import Flask
app = Flask(__name__)

@app.route('/loading/')
def hello_world():
    data = open('sample.html').read()    
    return data

if __== '__main__':
    app.run(Host='0.0.0.0')

これはより良くそして簡単に働きます。

2

すべての答えは良いですが、私にとってうまくいったのは、Flaskからの単純な関数send_fileを使用することだけです。 Host:port/ApiNameが出力を表示するときに、応答としてhtmlファイルを送信する必要がある場合に、これはうまく機能しますブラウザのファイル


@app.route('/ApiName')
def ApiFunc():
    try:
        return send_file('some-other-directory-than-root/your-file.extension')
    except Exception as e:
        logging.info(e.args[0])```

1
Binoy S Kumar

単にファイルを開こうとしているだけなら、app.open_resource()を使うことができます。そのため、ファイルを読むと次のようになります。

with app.open_resource('/static/path/yourfile'):
      #code to read the file and do something
0

簡単な方法の1つ。 乾杯!

demo.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
   return render_template("index.html")

if __== '__main__':
   app.run(debug = True)

templates というフォルダ名を作成します。 templates folder の中に index.html ファイルを追加します。

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Python Web Application</title>
</head>
<body>
    <div>
         <p>
            Welcomes You!!
         </p>
    </div>
</body>
</html>

プロジェクトの構成

-demo.py
-templates/index.html
0
Maheshvirus

デフォルトでは、flaskはすべてのテンプレートファイル(任意のプレーンテキストファイルですが、通常は.htmlまたはjinja2などのある種のテンプレート言語)を格納するための "templates"フォルダと、すべての静的ファイルを格納するための "static"フォルダを使用します。 .js.cssとあなたの画像)。
あなたのroutesでは、uはあなたの要求に対する応答としてテンプレートファイルをレンダリングするためにrender_template()を使うことができます(上で述べたように、デフォルトではtemplatesフォルダに置かれます)。そしてテンプレートファイル(通常は.htmlのようなファイルです)では、いくつかの.jsや `.css 'ファイルを使っているかもしれません。ですから、これらの静的ファイルをどのようにして現在のテンプレートファイルにリンクするかです。

0
Harvey