Flask基础(前端视角) 部署静态页面,配置接口,解决History路由

847 阅读4分钟

1 背景

在用Vue编写完前端页面后,下一步打包并将它部署到线上服务器上,这样我们的页面才会被别人访问到。对于前端开发的同学,没有太多时间去系统学习后端的知识,因此快速部署一个后端服务就显得很重要了。

出于方便,前端同学可以使用Node.js进行后端开发,我个人也是这么习惯的。但是这次出于项目需要需要使用python进行简单的后端开发,那只能一边踩坑一边学习,比较痛苦,也因此在这里以前端的视角来讲述一下这个过程,希望能让大家少踩点坑。

2 准备

  1. 将编写好的Vue工程进行打包,命令为npm run build,生成一个dist文件夹。
  2. 任意找一个位置,新建一个文件夹serve,结构如下
        ├─ serve
        |      ├─app.py      配置的服务器的文件
        |      ├─dist        前端资源夹
        |      ├─controller  接口配置文件夹
    
  3. 将Vue打包出的dist文件夹中的内容放在serve/dist文件夹下

3 最简单的Flask程序

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True,port=8100)
  1. 安装flask: pip install flask 引入flask from flask import Flask
  2. 注册app app = Flask(__name__) 这个记住写法就行
  3. 配置服务器运行在本机8100端口,debug设置为True有利于调试,只需要按下调试就可以自动重启服务,类似于nodemon的作用
if __name__ == '__main__':
    app.run(debug=True,port=8100)
  1. 这个部分作用就是注册路由'/'并绑定到函数hello_world上。实现的效果就是,当我们访问8100端口(在本地就是127.0.0.1:8100)的时候,hello_world函数会被执行,前端会拿到return函数里面的值。
@app.route("/")
def hello_world():
    return xxx

return函数可以return一个json数据也可以return一个HTML文件,后续就可以用这个方法配置接口并部署前端静态页面。

4 静态页面部署 history路由的解决 接口配置

静态页面部署

第一步修改静态文件的路径,配置到dist文件夹中

app = Flask(__name__, static_folder='dist')

使用app.send_static_file发送index.html,这样当浏览器访问8100端口的时候就可以出现网页内容了

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

其实这上面的过程达到的效果就是npm run serve的效果,但是会出现一个问题,如果前端配置的路由是history而不是hash,那么需要额外针对这个进行解决

history路由的解决

总体的思路就是如果遇到没有定义的path,就跳回到index.html,让前端去处理,这里特别避开了CSS JS IMG文件夹以及ico文件,防止代码要访问的时候出现问题。

@app.route('/<path:path>')
def history(path):       
    if path.startswith('css/') or path.startswith('js/')\
            or path.startswith('img/') or path == 'favicon.ico':
        return app.send_static_file(path)
    else:
        print(path)
        return app.send_static_file('index.html')

同时,网上有些教程推荐的配置是

app = Flask(__name__,static_folder='dist',static_url_path="")

这样写的话,在路由history配置的时候会出问题,如果非要写static_url_path,应该写成

app = Flask(__name__,static_folder='dist',static_url_path="/dist")

接口配置

@app.route('/hello',methods=["GET"])
def hello():
    return json.dumps({'status':0,'message':'成功访问Hello'}, ensure_ascii=False)

这里配置了一个GET接口'127.0.0.1:8100/hello',通过postman测试,发现可以使用

image.png

代码

from flask import Flask
from flask_cors import CORS
from config import Config
import json

app = Flask(__name__,static_folder='dist',static_url_path="/dist")
app.config.from_object(__name__)
app.config['JSON_AS_ASCII'] = False
CORS(app)

@app.route('/hello',methods=["GET"])
def hello():
    return json.dumps({'status':0,'message':'成功访问Hello'}, ensure_ascii=False)

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

@app.route('/<path:path>')
def history(path):       
    if path.startswith('css/') or path.startswith('js/')\
            or path.startswith('img/') or path == 'favicon.ico':
        return app.send_static_file(path)
    else:
        print(path)
        return app.send_static_file('index.html')

if __name__ == '__main__':
    app.run(debug=True, port=8100)

5 提升

显然,代码都放在同一个文件中是不可以接收的,那么就把接口的部分先拆分出来。

  1. 这里使用flask的蓝图来拆分不同的接口,在准备阶段我们已经创建了一个controller文件夹,在文件夹中新建一个 hello.py

  2. 引入Blueprint,并创建一个Blueprint对象

import json
from flask import Blueprint

# 创建了一个蓝图对象
hello = Blueprint('hello',__name__)

这个hello是等会儿要暴露出去的一个变量

  1. 配置两个post接口
@hello.route("/world", methods=["POST"])
def world():
    return json.dumps({'status':0,'message':'Hello world'},ensure_ascii=False)
@hello.route("/flask", methods=["POST"])
def flask():
    return json.dumps({'status':0,'message':'Hello flask'},ensure_ascii=False)
  1. 在app.py中使用
from controller.dialog import dialog
app.register_blueprint(dialog, url_prefix='/hello')

如果要访问这个hello.py里面的接口,必须是'/hello'开头的,比如说'/hello/world'

  1. 使用postman测试

image.png

image.png

代码汇总

#app.py
from flask import Flask, render_template
from flask_cors import CORS
from config import Config
from controller.hello import hello
import json
# 访问静态前缀暂时用不到
app = Flask(__name__,static_folder='dist',static_url_path="/dist")
app.config.from_object(__name__)
app.config['JSON_AS_ASCII'] = False
CORS(app)

app.register_blueprint(hello, url_prefix='/hello')



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

 
@app.route('/<path:path>')
def history(path):       
    if path.startswith('css/') or path.startswith('js/')\
            or path.startswith('img/') or path == 'favicon.ico':
        return app.send_static_file(path)
    else:
        print(path)
        return app.send_static_file('index.html')

if __name__ == '__main__':
    app.run(debug=True, port=8100)
#hello.py
import json
from flask import Blueprint

# 创建了一个蓝图对象
hello = Blueprint('hello',__name__)

#####################################################################################
@hello.route("/world", methods=["POST"])
def world():
    return json.dumps({'status':0,'message':'Hello world'},ensure_ascii=False)

#####################################################################################
@hello.route("/flask", methods=["POST"])
def flask():
    return json.dumps({'status':0,'message':'Hello flask'},ensure_ascii=False)

相关学习资料dormousehole.readthedocs.io/en/latest/q…