flask

如何使用flask做vue的静态文件服务器?

原理: 让flask的静态文件与模板文件的根目录指向vue的静态文件地址.

from flask import Flask, render_template
def create_static_app(folder_path):
    app = Flask(__name__,
                static_folder = folder_path,
                template_folder= folder_path)
  
    @app.route('/', defaults={'rel_path': ''})
    @app.route('/<path:rel_path>') #解析url地址
    def path_serve(rel_path):
        if rel_path.split(".")[-1] in ["js","css","ico","ttf","woff","map"]:
            # 这些文件都从静态文夹里面获取
            return app.send_static_file(rel_path)
        elif not rel_path:
            return render_template("index.html")
        else:
            raise ("cannot deal with {}".format(rel_path))
    return app

if __name__ =="__main__":
    app = create_static_app(r"D:\gdrive\js_swz\searchtest\app\dist")
    app.run(host="192.168.1.9", port=9200, debug=True)

坑: flask的render_template方法会自动使用jinja2的语法来替换{{var}}.替换为空字符之后,vue再解析的时候就没有这些大括号了.最简单的处理方式是用app.send_static_file方法,这个方法不会去替换{{var}}

如何让flask自动热加载?

flask执行.run方法的时候,可以把debug选项改为True,这样可以热加载了.下图中我修改了main.py文件,然后flask感应到这个修改,执行了reload.


热加载示意

热更新的细节: 如果flask所以来的其他模块变化了,它自己会更新吗?

如何使用flask来处理post请求?

server端:

@app.route('/text', methods=['POST', 'GET'])
def convert_code():
    """
    使用reqeust.get_data()方法才能得到传进来的json
    :return:
    """
    code_text = request.get_data()
    json_data = json.loads(code_text.decode("utf-8"))
    text_content = json_data['text']

web端(jinjia模板):

let xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","http://{{host_ip}}:5000/text",true);
xmlhttp.send(JSON.stringify({text:t.value}));

flask 如何做文件服务器

核心是使用send_from_directory这个函数来获取指定路径上的文件.

from flask import Flask
from flask import request, render_template, make_response, jsonify,send_from_directory
from run_fishsite.instance import config as instance_cf
app = Flask(__name__)
@app.route("/phtml/<path:rel_path>")
def show_phtml(rel_path):
     return send_from_directory(instance_cf.phtml_dir, rel_path, as_attachment=False)  # as_attachment代码是下载还是打开

上传文件会略微复杂一下,可以使用原生的flask,也可以使用插件:https://pythonhosted.org/Flask-Uploads/

如何使用flask_login实现登录?

实现思路: 1. 实现登录认证. 2. 实现登录状态保持. 3. 同一个url根据登录状态来返回不同结果.
在flask_login库中登录状态是由User类的对象保持的.不同的session会有不同的User类对象. 这个插件封装了session中的设置.
flask_login本身的函数提供了必要的操作流程,包括login_user函数, logout_user函数.
log_manager是为了给flask_login提供扩展,可以配置不同的回调函数.包括user的id设置,未登录提示,current_user等.

#coding=utf-8
import flask
import flask_login
# ------------------------- 配置 -------------------------
secret_key =  'super secret string'  # flask要求任何与session相关的操作都需要密钥来确保安全性.
users = {'foo@bar.tld': {'password': 'secret'}}
app = flask.Flask(__name__)
app.secret_key = secret_key
# ------------------------- 定义User -------------------------
class User(flask_login.UserMixin): # 继承了基本的用户模型, User基本上就是一些属性的集合而已.
    pass

# ------------------------- 配置login_manager-------------------------
login_manager = flask_login.LoginManager()
login_manager.init_app(app) # 绑定到app中去

@login_manager.unauthorized_handler
def unauthorized_handler():
    return 'Unauthorized'


@login_manager.user_loader # 把user_loader挂载到login_manager上, 接受一个用户id作为参数,然后返回none或者user实例.
def user_loader(email):
    print("I am user_loader")
    if email not in users:
        return

    user = User() # 登录成功,新建一个User实例
    user.id = email
    return user


@login_manager.request_loader
def request_loader(request): # 不使用cookie的登录方法,可以直接从request对象中获取登录状态;flask-login会优先检查请求的cookie,当发现用户cookie不存在的时候才会根据request来验证
    print("I am request_loader")
    email = request.form.get('email')
    if email not in users:
        return

    user = User()
    user.id = email

    # DO NOT ever store passwords in plaintext and always compare password
    # hashes using constant-time comparison!
    user.is_authenticated = request.form['password'] == users[email]['password']  # 对比密码
    return user
# ------------------------- 使用flask_login-------------------------
@app.route('/login', methods=['GET', 'POST']) # 绑定登录页面
def login():
    if flask.request.method == 'GET':
        return '''
               <form action='login' method='POST'>
                <input type='text' name='email' id='email' placeholder='email'/>
                <input type='password' name='password' id='password' placeholder='password'/>
                <input type='submit' name='submit'/>
               </form>
               ''' # 返回输入框

    email = flask.request.form['email'] # 得到用户名(email)
    if flask.request.form['password'] == users[email]['password']: # 校验密码
        user = User()
        user.id = email
        flask_login.login_user(user) # 让用户登录进去, 此时会调用user_loader函数
        return flask.redirect(flask.url_for('protected')) # 登录之后的重定向到/protected, url_for是一个类似于相对路径的概念.

    return 'Bad login'# 密码不对


@app.route('/protected')
@flask_login.login_required # 需要登录
def protected():
    return 'Logged in as: ' + flask_login.current_user.id # flask_login.current_user能够识别出当前的userid, flask_login维护一个比login_manager更上层的状态

@app.route('/logout')
def logout():
    flask_login.logout_user()
    return 'Logged out'
# ------------------------- 运行app-------------------------
app.run(host="192.168.1.4", port=5004, debug= True)

如何处理报错?

@app.errorhandler(401)
def page_not_found(e):
    return Response('<p>Login failed</p>')

静态文件夹与路由的冲突

如果设置了静态文件夹,flask会自动根据url的地址来去静态文件中获取相应的文件.这样就忽略了用户自定义的路由函数.

app = Flask(__name__, static_folder=r"\\192.168.1.9\searchtest\app\static")
@app.route('/', defaults={'rel_path': ''})
@app.route('/path:rel_path>')
def path_serve(rel_path):
# mycode

此时所有get \static***这样的请求都会去静态文件夹中去找相应的文件.而忽略掉path_server

端口冲突的坑

某些端口能够启动flask,但是请求就是发不到flask上去.=>需要提前检查端口占用,被占用了就报错.

路由不识别根目录

@app.route("/dataeditor/<path:rel_path>")使用这样的路由会导致dataedtor这个根目录无响应.
坑: 默认的模板路径为templates而不是template

flask的自动多线程

使用了aiohttp这个异步请求的方法可以探知到flask自带多线程执行的.
案例1: 在view函数中,使用time.sleep(1), 然后连续发起两个请求,总耗时1.01秒左右.
案例2: 在view函数中使用全局变量,也不影响flask的时间消耗.

cout = [1]
    @app.route("/")
    def home():
        html_str = """
        cout[0] = cout[0] + 1
        print(cout[0])
        time.sleep(1)
        # return html_str
        return str(cout)

但是,如果调用了一个堵塞的io接口,那么会阻塞flask多线程的执行.例如tdx的交易接口.此时可以开启另一个tdx连接实例来降低延时.

坑: reqeust一般需要在view函数才可以引用.

flask多线程,可以使用 flask.copy_current_request_context这个装饰器,来获取当前的request中的信息.

参考:http://flask.pocoo.org/docs/1.0/api/#flask.copy_current_request_context

可以使用celery来实现后台进程,来不断地update数据.
http://flask.pocoo.org/docs/1.0/patterns/celery/

如何传递列表给flask

res = requests.get("http://192.168.1.4:5004/try_list", json=[1,3,4]) # 在flask 那边需要使用request.get_json来解析出列表来

坑: post请求被识别为get请求

如果post后面不加反斜杠的话,会被认为是get请求

requests.post(192.168.1.4:5000/ymarket, data=a_dict) # flask端会认为是get请求

坑: 在pycharm中启动flask

在pycharm中执行flask程序,会自动忽略app.run命令.因此需要在配置中配置好host与port


image.png

1

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容