简体   繁体   English

为 static 文件提供 flask 用于开发和 nginx 用于生产

[英]Serve static files with flask on development and nginx on production

Let's say I've got this mcve:假设我有这个 mcve:

mcve.py mcve.py

import textwrap
from pathlib import Path
from flask import Flask


working_dir = Path(__file__).parent
app = Flask(
    __name__,
    # static_folder=str(working_dir / "uploads"),
)


@app.route("/test")
def index():
    return textwrap.dedent(
        """
        <!DOCTYPE html>
        <html>
        <head>
            <title>Hello world</title>
        </head>
        <body>
            <img src="foo/foo.png">
            <img src="bar/bar.png">
        </body>
        </html>
    """
    ).strip()


if __name__ == "__main__":
    with app.test_client() as c:
        print(c.get("/test").data.decode("utf-8"))

run.bat运行.bat

set FLASK_APP=mcve.py
set FLASK_ENV=development
flask run

If I execute run.bat and then I go to http://localhost:5000/test in the browser I'll get:如果我在浏览器中执行run.bat然后我 go 到http://localhost:5000/test我会得到:

>flask run
 * Serving Flask app "x.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with windowsapi reloader
 * Debugger is active!
 * Debugger PIN: 497-008-397
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [31/May/2020 22:32:19] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /test HTTP/1.1" 200 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /foo/foo.png HTTP/1.1" 404 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /bar/bar.png HTTP/1.1" 404 -

Question问题

How should I modify mcve.py to server the images properly (now you can see is giving 404) in development using flask's server but then serve them properly with nginx on production?我应该如何修改mcve.py以使用烧瓶的服务器在开发中正确地服务器图像(现在您可以看到给出 404),然后在生产中使用 nginx 正确地为它们提供服务?

You don't have to configure flask specifically for this.您不必为此专门配置 flask。 These logs:这些日志:

127.0.0.1 - - [31/May/2020 22:32:19] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /test HTTP/1.1" 200 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /foo/foo.png HTTP/1.1" 404 -
127.0.0.1 - - [31/May/2020 22:32:22] "GET /bar/bar.png HTTP/1.1" 404 -

are actually generated by the werkzeug development server that's serving the static content for you.实际上是由为您提供 static 内容的 werkzeug 开发服务器生成的。 When you move to using nginx, you can intercept the GET requests with a URL rule.当您转而使用 nginx 时,您可以使用 URL 规则拦截 GET 请求。 From the example nginx config file from the Flask Mega Tutorial :Flask 超级教程中的示例 nginx 配置文件:

...

server {

    ...

    location / {
        # forward application requests to the gunicorn server
        proxy_pass http://localhost:8000;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static {
        # handle static files directly, without forwarding to the application
        alias /home/ubuntu/microblog/app/static;
        expires 30d;
    }
}

Note the /location rule that handles requests to static directly, so those requests from the browser wouldn't even hit whatever is serving your flask app in production.请注意直接处理对static的请求的/location规则,因此来自浏览器的这些请求甚至不会命中在生产中为您的 flask 应用程序提供服务的任何内容。 There are many more methods for matching urls that you can find, eg here .您可以找到更多匹配 url 的方法,例如这里 It's perfectly possible to add multiple such rules to look in separate locations but you'll want to structure the app to give these files a distinct location so you can implement such rules.完全可以添加多个此类规则以查看不同的位置,但您需要构建应用程序以赋予这些文件一个不同的位置,以便您可以实施此类规则。


Separately, to get around your current 404s, look at thetemplate docs for Jinja2 and use the url_for method to make sure it resolves relative paths correctly.另外,要绕过当前的 404,请查看Jinja2 的模板文档并使用url_for方法确保它正确解析相对路径。

For example, if I want to include:例如,如果我想包括:

<link href='static/css/bootstrap-4.3.1.min.css' rel="stylesheet">

I would instead use:我会改为使用:

<link href="{{ url_for('static', filename='css/bootstrap-4.3.1.min.css') }}" rel="stylesheet">

This passes off the responsibility of path resolution to the app, so no matter how many hyperlinks I've followed or blueprints I'm using, this path will always resolve to the correct static directory when the template is rendered.这将路径解析的责任转移给了应用程序,因此无论我遵循了多少超链接或使用了多少蓝图,在呈现模板时,此路径将始终解析为正确的static目录。

I'm not sure this will work with return textwrap.dedent because it might not invoke Jinja on the template.我不确定这是否适用于return textwrap.dedent因为它可能不会在模板上调用 Jinja。 You can import render_template_string for a throwaway example like you have here, but render_template will work in your actual app too.您可以像这里一样为一次性示例导入render_template_string ,但render_template也可以在您的实际应用程序中使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM