flask入门

1.flask介绍 

  Flask是Python编写的一款轻量级Web应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。
  Flask使用 BSD 授权。其中两个环境依赖是Werkzeug和jinja2,这意味着它不需要依赖外部库,正因如此,我们将其称为轻量级框架。
  Werkzeug是一个WSGI工具集,作为一个 Web 框架的底层库,它封装好了很多 Web 框架的东西,例如 Request,Response 等。

flask:

  1. 轻,短小精悍
  2. 快,三行代码开启服务
  3. 自带组件少,大多数来源第三方,flask-admin,flask-session
  4. flask大版本更新,组件更新速度慢

django:

  1. 大而全,admin,models,Form,中间件
  2. 一个框架解决所有问题
  3. 一旦启动,所有资源全部加载
  4. 太大,结构复杂
  5. 所有组件都有django组件自身控制 

tornado:

  1. 原生websocket
  2. 异步IO
  3. 非阻塞
  4. 几乎无三方及原生组件,连session都不支持

flask常用扩展包

Flask-SQLalchemy:操作数据库;
Flask-script:插入脚本;
Flask-migrate:管理迁移数据库;
Flask-Session:Session存储方式指定;
Flask-WTF:表单;
Flask-Mail:邮件;
Flask-Bable:提供国际化和本地化支持,翻译;
Flask-Login:认证用户状态;
Flask-OpenID:认证;
Flask-RESTful:开发REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和时间;
Flask-Admin:简单而可扩展的管理接口的框架

2.开启flask

2.1简单运行  ----->(先通过终端安装flask(版本号1.0.2))

尝试运行:

from flask import Flask

app = Flask(__name__)  # 模块名称将会作为单独应用启动还是作为模块启动而有不同,只有这么起名,Flask才知道去哪里找模板,静态文件等
@app.route("/")    # 使用route装饰器告诉Flask什么样的URL可以出发我们的视图函数
def index():
    return "hello flask"

# 这里常规写法还是加上if __name__ == "__main__"比较好,确保服务器只会在该脚本被python解释器执行的时候运行,而非作为模板导入的时候  

效果

3.render_template,redirect,HttpResponse,jsonify

3.1 HttpResponse

@app.route("/")
def index():
    return "hello flask"    # 这里的return等同HttpResponse,直接返回字符串

3.2 Redirect 

 和django中的一样,用于重定向

from flask import Flask,redirect

app = Flask(__name__)

@app.route('/index')
def index():
    return redirect("/")    # 跳转到根目录页面


@app.route('/')
def main():
    return "ok"

if __name__ == "__main__":
    app.run("0.0.0.0",5005,debug=True)

当我们访问url:  http://127.0.0.1:5000/index的时候,它会触发redirect("/")跳转到该地址,并触发对应的视图函数main

3.3 render_template

  这里的render_template等同我们django中的render,不过在此我们需要创建一个html标签来接收

  这里需要创建一个在同级目录下创建一个templates文件(必须叫它,源码规定),用于存放我们的html标签

from flask import Flask,render_template

app = Flask(__name__)

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


if __name__ == "__main__":
    app.run("0.0.0.0",5005,debug=True)

说明:

  这里一般需要指定我们的templates路径,否则会飘黄,因为模板语言采用的是jinja2,而django采用的模板语言是django,我们需要进行设置,或者选择在setting中设置

3.4 jsonify

  使用 Flask 写一个接口时候需要给客户端返回 JSON 数据,在 Flask 中可以直接使用 jsonify 生成一个 JSON 的响应

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

# 返回JSON
@app.route('/demo')
def demo():
    json_dict = {
        "user_id": 10,
        "user_name": "laowang"
    }
    return jsonify(json_dict)

if __name__=="__main__":
    app.run(debug=True)

效果:

# 不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,如果是 JSON 需要指定 content-type:application/json

4. 关于request

4.1 简单说明

 django的接口是依据uwsgi

 flask依赖一个实现wsgi协议的模块:werkzeug

 flask使用了werkzeug库中的MapRule来管理url与处理函数映射关系

 它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple

@Request.application
def hello(request):
    print(request)      # <Request 'http://localhost:4000/' [GET]>
    print(request.method)       # GET
    print(request.url)      # http://localhost:4000/
    print(dir(request))     # 获取所有的方法
    return Response('Hello World!')

if __name__ == '__main__':
    run_simple('localhost', 4000, hello)    # 执行该函数

4.2 request下常用参数说明:

request.method  
# 前端用什么方式提交,常见是GET和POST

request.form   
 # Form表单中传递过来的值使用 request.form 中拿到,打印request.form,值 ImmutableMultiDict([('user', 'learning'), ('pwd', '666')]),可看做成字典
  
request.args    
# url中传递的参数,即get请求中问号结尾后面的数据,类似django中的request.get,原始样式ImmutableMultiDict([('id', '2')])

reques.values    
# 获取所有参数,打印值 CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('age', '20')]), ImmutableMultiDict([('user', 'learning'), ('pwd', '666')])])

# 它可以通过打印 request.values.to_dict() 把值全部转化成字典形式

# 从这里可以看出,有些情况下url中的key和form中的key会重名,此时会出现覆盖的情况,生产环境中一定要注意该情况(form中的key会覆盖url中的key)

request.cookies   
# 存在浏览器端的字符串儿也会一起带过来

request.heads   
# 获取请求的请求头

request.data    
# 将处理不了的数据类型转换成json存入data中  # 数据类型参考手册

request.files    
# 遇到文件上传,request.files 里面存的是你上传的文件

request.path
# 获取当前的url路径

request.url
# 当前url的全部路径

request.script_root
# 当前url路径的上一级路径

request.url_root
# 当前url的路径的上一级全部路径

request.json
# 如果在请求中写入了 "application/json" 使用 request.json 则返回json解析数据, 否则返回 None

获取参数request.args的使用

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

@app.route('/flask/')
def index():
    id = request.args.get('id')
    return '获取id是%s'% id

if __name__ == "__main__":
    app.run(debug=True)

效果

request.file上传文件说明

  1. 一个 <form> 标签被标记有 enctype=multipart/form-data ,并且在里面包含一个 <input type=file> 标签。
  2. 服务端应用通过请求对象上的 files 字典访问文件。
  3. 使用文件的 save() 方法将文件永久地保存在文件系统上的某处。

 login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>欢迎登陆</h4>
<form action="/req" method="post" enctype="multipart/form-data">
    <p>
        <input type="file" name="file">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

 # 前端页面必须设置enctype="multipart/form-data",否则提交时会报错

app.py

from flask import Flask  
from flask import render_template  
from flask import request  

app = Flask(__name__)

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


@app.route("/req",methods=["POST","GET"])
def home():
    print(request.files)  # ImmutableMultiDict([('file', <FileStorage: '5.jpg' ('image/jpeg')>)])
    print(request.files["file"])  # <FileStorage: '5.jpg' ('image/jpeg')>
    my_file = request.files["file"]
    print(type(my_file))    # <class 'werkzeug.datastructures.FileStorage'>
    my_file.save("aa.jpg")      # 这里写的有问题,图片过来名字就换了,而且还需判断发送的文件类型
    return "ok"

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

# 这里写的文件保存这里写的比较粗略,详细介绍可参考源码说明

5. 关于response

视图函数中可以返回的类型:

  字符串,返回的字符串其实底层将这个字符串包装成了一个‘Response’对象

  元祖,和字符串一样

  response及其子类

如何返回其他类型呢??这就需要我们自定义一个Response对象,他继承自Response,套用了多继承下BaseResponse的force_type方法

from flask import Flask,url_for,Response,jsonify

app = Flask(__name__)

class JsonResponse(Response):

    @classmethod
    def force_type(cls, response, environ=None):
        '''
        这个方法只有视图函数返回非字符、非元祖、非Response对象才会调用
        '''
        #把字典转换成json
        if isinstance(response,dict):
            #jsonify将字典转换成json对象,还将该对象包装成了一个Response对象
            response = jsonify(response)
        return super(JsonResponse, cls).force_type(response,environ)

app.response_class = JsonResponse   # 指定app.response_class为你自定义的Response对象

@app.route('/list1/')
def list1():
    return Response('list1')  #合法对象,可以直接返回

@app.route('/list3/')
def list3():
    return {'username':'learning','age':22}   #返回的是非字符非元祖非Response对象,执行force_type方法

if __name__ == "__main__":
    app.run(port=5225,debug=True)

效果

6. 关于__name__的说明

app1下:
import app2
print("这在app1中",__name__)


app2下:
print("app2",__name__)

这里我在app1下打印:

 # 这里需要强调的是,如果是在自己的文件下,__name__就是__main__,如果是从其他文件导入进来,则__name__就是它的文件名

原文地址:https://www.cnblogs.com/LearningOnline/p/9590089.html