01-flask创建/路由/http请求与相应

一、关于Flask

Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。

与django做对比:

如果做一个小型项目用django做是比较笨重的,django下载加上其他的一些包,运行速度其实是不快的,一个小型项目有很多包是用不上的

为了保证我们实现的功能是高定制性的,很多公司都采用flask

牛逼点的公司直接用flask做些大项目,性能肯定比django要好

Flask就是一个核心类而已,核心类只提供了3-4个包给我们,其他所有的包按需安装

其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。

Flask常用第三方扩展包:

  • Flask-SQLalchemy:操作数据库,ORM;

  • Flask-script:终端脚本工具,脚手架;

    • 这一系列终端脚本工具用一个名词来表达它,脚手架
    • 把自己编好的一些工具,通过简单命令就可以生成一个目录或数据或文件的这种工具称脚手架工具
  • Flask-migrate:管理迁移数据库;

  • Flask-Session:Session存储方式指定;

    • 可以把Session转移他的存储方式,在以前默认是存储在文件中,后面存到了mysql数据库里面,存到redis的话,需要安装
  • Flask-WTF:表单;

    • django中可以通过Model From自动生成表达,
  • Flask-Mail:邮件;

  • Flask-Bable:提供国际化和本地化支持,翻译;

  • Flask-Login:认证用户状态;

  • Flask-OpenID:认证, OAuth;

  • Flask-RESTful:开发REST API的工具;

  • Flask JSON-RPC: 开发rpc远程服务[过程]调用

  • Flask-Bootstrap:集成前端Twitter Bootstrap框架

    • 安装admiin如果要切换一个主题,要安装Bootstrap
  • Flask-Moment:本地化日期和时间

    • 用到日期时间的转换,需要安装
  • Flask-Admin:简单而可扩展的管理接口的框架

二、简单应用flask

创建虚拟环境

mkvirtualenv flask -p python3

安装flask

pip install flask==0.12.5

安装完只提供这几个模块

  • Jinja2-2.11.2:模板引擎
  • MarkupSafe-1.1.1:编码转换工具 主要针对html里面的大于号小于号转换为& lt
  • Werkzeug-0.16.1:路由模块
  • click-7.1.2:时间监听系统
  • flask-0.12.5:flask本身内核,flask本身写的那个类
  • itsdangerous-1.1.0:数据加密传输
pip freeze

 

新建一个文件夹 flask_demo

新建一个文件main.py

from flask import Flask

# 创建应用对象
app = Flask(__name__)

# 视图加载
@app.route(rule="/") # 声明路由
def index():    # 声明视图函数
    return "<h1>python31</h1>"  # 直接通过return返回普通字符串

if __name__ == '__main__':
    # 启动项目,不要在run 后面写任何代码,不会被执行到
    app.run(debug=True, port=8000,host="0.0.0.0") #wsgiref模块提供的

 

首先在flask包里有一个全局对象,充当一个应用,

每一个网站只有一个唯一的app,通过flask创建,创建时需要拿到我们的这个文件,所以就把__name__传进去

app提供了flask所有要用的东西,其中有一个route,是设置路由的

装饰视图函数

app.run(),启动了我们的测试服务器,由wsgiref模块提供的

有两个参数

debug=True 默认是不会重启的,因为默认debug=False,为True就启动了debug模式

port=8000 绑定了8000端口

host="0.0.0.0" 任意客户端都能访问

1、Flask() 参数

    def __init__(self, import_name, static_path=None, static_url_path=None,
                 static_folder='static', template_folder='templates',
                 instance_path=None, instance_relative_config=False,
                 root_path=None):
"""
import_name      Flask程序所在的包(模块),传 __name__ 就可以
                 其可以决定 Flask 在访问静态文件时查找的路径
static_path      静态文件访问路径(不推荐使用,使用 static_url_path 代替)
static_url_path  静态文件访问路径,可以不传,默认为:/ + static_folder
static_folder    静态文件存储的文件夹,可以不传,默认为 static
template_folder  模板文件存储的文件夹,可以不传,默认为 templates
"""

三、加载配置

from flask import Flask

# 1. 实例化flask 应用对象
app = Flask(__name__)

# 1.1 配置信息
class Config():
    # 配置项目运行在debug调试模式下
    DEBUG = True

# 1.1 加载配置到应用对象中
app.config.from_object(Config)

# 2. 编写视图和路由
@app.route(rule="/", methods=["get"])
def index():
    return "<h1>hello flask</h1>"

if __name__ == '__main__':
    app.run()

加载配置到应用对象,加载有五种方式

  • app.config.from_envvar: 表示从环境变量里提取我们要的数据
  • app.config.from_json: 从json文件中读取
  • app.config.from_mapping: 一种映射关系,类似于字典的键值对
  • app.config.from_object: 通过对象
  • app.config.from_pyfile: 通过模块

四、路由的基本使用、自定义路由转换器

路由和视图的名称必须全局唯一,不能出现重复,否则报错。

什么是路由:

一种访问地址[url]和应用程序[视图]进行一对一绑定的映射关系

在开发中,我们所说的路由,其实通常指代完成路由绑定关系订单路由类

url中可以传递路由参数, 2种方式

1、任意路由参数接收

from flask import Flask

# 1. 实例化flask 应用对象
app = Flask(__name__)

# 1.1 配置信息
class Config():
    # 配置项目运行在debug调试模式下
    DEBUG = True

# 1.1 加载配置到应用对象中
app.config.from_object(Config)

# 2. 编写视图和路由
@app.route(rule="/", methods=["get"])
def index():
    return "<h1>hello flask</h1>"

@app.route(rule="/user/<user_id>") # 没有限定参数的类型,所以user_id可以是数字,也可以是其他类型的信息
def user(user_id):
    print(user_id)
    return "<h1>hello user</h1>"


if __name__ == '__main__':
    app.run()

 视图函数的参数名称必须与路由上面的保持一致,否则接收不了

1.1、限定路由参数的数据类型

通过路由转换器限定路由参数的类型,flask系统自带转换器编写在werkzeug.routing.py文件中。底部可以看到以下字典:

DEFAULT_CONVERTERS = {
   "default": UnicodeConverter,
   "string": UnicodeConverter,
   "any": AnyConverter,
   "path": PathConverter,
   "int": IntegerConverter,
   "float": FloatConverter,
   "uuid": UUIDConverter,
}

默认路由转换器,是一个字典

系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

转换器名称描述
string 默认类型,接受不带斜杠的任何文本
int 接受正整数
float 接受正浮点值
path 接收string但也接受斜线
uuid 接受UUID(通用唯一识别码)字符串 xxxx-xxxx-xxxxx-xxxxx
from flask import Flask

# 创建应用对象
app = Flask(__name__)

# 加载配置
class Config():
    DEBUG = True

app.config.from_object(Config)

# 路由转换器对路由参数的类型进行限定
@app.route(rule="/<float:user_id>")
def index(user_id):
    print(type(user_id))  # <class 'float'>
    return "user_id=%s" % user_id


if __name__ == '__main__':
    app.run()

 

默认路由转换器不能满足我们的具体业务,比如希望接收一个字符串,但是这个字符串必须数字组成,有时候还要限定是手机格式,邮箱格式等,通过上面的七个是解决不了的

1.2、自定义路由转换器

参考默认的模式写自定义路由转换器

必须直接或间接继承BaseConverter,提供了识别路由的方案

定义规则

map 就是 url_map

类似django里面的urlpatterns app.url_map 每个成员就是一个类

然后把我们自己写的类映射进去

 

from flask import Flask

# 实例化flask 应用对象
app = Flask(__name__)

# 自定义路由参数转换器
# 1. 引入BaseConverter路由参数转换器基类
from werkzeug.routing import BaseConverter

# 2. 自定义路由参数转换器
class MobileConverter(BaseConverter):
    regex = r"1[3-9]\d{9}"
    def __init__(self,map,*args,**kwargs):
        super().__init__(map,*args,**kwargs)

# 3. 注册路由参数转换到app应用对象中
app.url_map.converters["mobile"] = MobileConverter

# 编写视图和路由
@app.route(rule="/user/<mobile:user_mobile>")
def user(user_mobile):
    print(user_mobile)
    return "<h1>hello user</h1>"

# url_map是flask路由列表对象,类似之前在django里面的urlpatterns

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

 

这样写有个不好的点就是,写了一个正则限定的类,将来如果有更多的格式要求,那每一个都要写一个路由转换器,这样就特别麻烦

直接在路由里面写正则参数

1.3、基于路由参数转换器实现类似django的re_path效果接收正则限定参数

from flask import Flask

# 实例化flask 应用对象
app = Flask(__name__)

# 基于自定义路由参数转换器实现类似django的re_path这样的正则路由参数
# 1. 引入BaseConverter路由参数转换器基类
from werkzeug.routing import BaseConverter

# 2. 自定义路由参数转换器
class RegexConverter(BaseConverter):
    def __init__(self,map,*args):
        super().__init__(map)
        self.regex = args[0]

# 3. 注册路由参数转换到app应用对象中
app.url_map.converters["re"] = RegexConverter

# 编写视图和路由
@app.route(rule="/user/<re('\d{6}'):mobile>")
def user(mobile):
    print(mobile)
    return "<h1>hello user</h1>"

# url_map是flask路由列表对象,类似之前在django里面的urlpatterns

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

 2、指定请求方式

from flask import Flask

app = Flask(__name__)

# 路由转换器对路由参数的类型进行限定
@app.route(rule="/",methods=["POST","PUT","PATCH","DELETE"])
# @app.route(rule="/") # 没有填写第二个参数methods则默认只能通过get请求访问
def index():
    return "ok"

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

五、路由与视图分离

from flask import Flask
app = Flask(__name__)

def index():
    return 'Hello World'

# 也可以让路由注册和视图进行分离
app.add_url_rule(rule="/", view_func=index)

if __name__ == '__main__':
    app.run()

六、http请求和相应

1、http请求

声明request对象

from flask import request

request就可以帮我们获取客户端里的数据,包括路径上的字符串、请求头、请求体等等信息

文档: http://docs.jinkan.org/docs/flask/api.html#flask.request

  • request:flask中代表当前请求的 request 对象

  • 作用:在视图函数中取出本次请求数据

  • 导入from flask import request

  • 代码位置:from flask.app import Request

常用的属性如下:

属性说明类型
data 记录请求体的数据,并转换为字符串 只要是通过其他属性无法识别转换的请求体数据 最终都是保留到data属性中 bytes类型
form 记录请求中的html表单数据 MultiDict
args 记录请求中的查询字符串,也可以是query_string MultiDict
cookies 记录请求中的cookie信息 Dict
headers 记录请求中的请求头 EnvironHeaders
method 记录请求使用的HTTP方法 GET/POST
url 记录请求的URL地址 string
files 记录请求上传的文件列表 *
json 记录ajax请求的json数据 json

获取提交请求的html表单数据

from flask import Flask,request
from werkzeug.datastructures import ImmutableMultiDict

app = Flask(__name__)

@app.route("/form",methods=["POST","PUT","PATCH"])
def get_form():
    print(request) # HTTP请求处理对象
    # 接受表单数据
    print(request.form)
    """打印效果:
    ImmutableMultiDict([('username', 'xiaoming'), ('password', '123456'), ('lve', 'swimming'), ('lve', 'game'), ('lve', 'shopping')])
    # ImmutableMultiDict 这个类就是一个字典的子类,我们可以称之为类字典对象,所以可以通过字典的操作来使用。
    # 思路来源: from collection import OrderedDict
    """
    # 获取指定键的单个值
    print(request.form.get("username"))
    print(request.form["username"])
    print(request.form["lve"]) # 如果键对应的数据有多个值,则不能通过get或中括号

    # 获取指定键获取多个值
    print(request.form.getlist("lve")) # ['swimming', 'game', 'shopping']

    # 格式转换
    # ImmutableMultiDict 转换成基本格式
    # 注意: 转换过程中,如果出现一个键对应多个值的情况,则取第一个值
    ret = request.form.to_dict() # {'username': 'xiaoming', 'password': '123456', 'lve': 'swimming'}
    
    return "ok"

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

获取query_params

查询字符串,不限任何的请求类型,通过地址+? 127.0.0.1:8000?aa=1

获取请求头

from flask import Flask,request
from werkzeug.datastructures import ImmutableMultiDict

app = Flask(__name__)

@app.route("/query")
def get_query_params():
    """获取查询字符串 query_params"""
    print(request.args)
    """打印效果:
    ImmutableMultiDict([('username', 'xiaoming'), ('age', '18')])
    """
    print(request.args.to_dict()) # {'username': 'xiaoming', 'age': '18'}
    return "ok"

@app.route("/head")
def get_head():
    """获取请求头数据"""
    print(request.headers)
    print(request.headers["Content-Type"]) # application/x-www-form-urlencoded

    # 获取自定义请求头[首字母大写,不支持多个单词使用横杠进行拼接的写法,也不支持多字节字符]
    print(request.headers["Company"]) # oldboyedu
    return "ok"

@app.route("/",methods=["POST","GET"])
def index():
    print(request.method) # GET 获取本次客户端的请求方法名
    print(request.url) # http://127.0.0.1:5000/  url地址
    print(request.json) # {'pay_type': 1, 'credit': 0, 'coupon': 0} 获取json数据

    print(request.files) # ImmutableMultiDict([('video1', <FileStorage: 'demo.mp4' ('video/mp4')>)])
    print(request.files.get("video1"))
    return "ok"

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

 

获取请求数据所有

from flask import Flask

# 实例化flask 应用对象
app = Flask(__name__)

# 编写视图和路由
from flask import request
from urllib.parse import parse_qs
@app.route(rule="/user", methods=["get","post","put","patch","delete"])
def user():
    # print(request.method) # 获取本次客户端的http请求方法         GET
    # print(request.path)  # 获取本次客户端请求的路由路径部分[去掉域名端口]    /user
    # print(request.url) # 获取本次客户端请求的http url地址        http://127.0.0.1:5000/user?user=1

    # 获取查询字符串
    # print(request.query_string)  # 获取本次客户端的(原始)查询字符串    b'user=1'
    # query_string = parse_qs(request.query_string)
    # print(query_string)  # {b'lve': [b'swimming', b'pingpang']}
    # print(query_string["lve".encode()][0].decode())
    # print(request.args)          # 获取本次客户端的(Dict字典)查询字符串  from collections import OrderedDict
    # print(request.args.get("lve"))  # 提取一个值
    # print(request.args.getlist("lve")) # 提取多个值
    print(request.args.to_dict())  # {'lve': 'swimming'}
    """
    ImmutableMultiDict的实例对象 提供了四个常用的方法给我们获取数据,
    1. get 获取指定参数的第一个值
    2. getlist 获取指定参数的多个值
    3. to_dict 把所有参数转换成字典[request对象的部分属性不支持]
    4. to_list 把所有参数转换成列表[request对象的部分属性不支持]
    """
    # 获取html表单,视图必须支持post方法访问
    # print(request.form)    # 表单中的全部数据
    # print(request.form.get("username")) # 表单单个数据
    # # 获取ajax或者表单中的上传文件都需要使用request.files
    # print(request.files.get("avatar"))  # <FileStorage: '2.jpg' ('image/jpeg')>

    # 获取json数据
    # print(request.json)  # {'username': 'xiaohuihui'}

    # 获取请求头
    # print(request.headers) #
    print(request.headers.to_list()) # 获取请求头
    # print(request.headers.get("Host")) # 获取请求头,REMOTE_ADDR客户端的地址
    print(request.headers.get("Company")) # 获取自定义请求头,首字母大写

    # 其他属性
    print(request.is_json) # 是否是ajax请求
    
    return "<h1>hello user</h1>"

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

 

 

2、响应

from flask import Flask,request,make_response,Response,jsonify

app = Flask(__name__)

@app.route("/")
def index():
    """返回html数据"""

    # return "ok"
    # return make_response("ok") # 上面的代码是这段代码的简写
    # return Response("ok") # 上面make_response本质上就是Response

    """返回json格式数据"""
    # data = {"name":"xiaoming","age":13}
    # return jsonify(data)

    """返回其他类型数据"""
    # 关于Response常用的参数
    # Response(response="内容", status="http响应状态码",headers=自定义响应头,mimetype="数据格式")
    # return Response(response="ok",status=201,headers={"company":"hello"})
    # 返回图片信息
    with open('./1.zip',"rb") as f:
        content=f.read()
    # 判断权限,身份...
    return Response(response=content,mimetype="application/zip")

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

make_response:

调用视图,判断视图执行的返回值是不是reponse的一个实例对象,如果不是就把内容再实例化一遍

3、重定向

from flask import Flask,redirect,url_for
app = Flask(__name__)

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

# 站内跳转,进行视图之间的跳转
@app.route("/")
def home():
    # 视图之间的跳转,可以携带get参数
    return redirect(url_for("index",name="xiaoming"))

# 跳转到站外地址
@app.route("/go")
def go():
    return redirect("http://www.baidu.com")

 

原文地址:https://www.cnblogs.com/kongxiangqun/p/14000970.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Jinja2:是Python的Web项目中被广泛应用的模板引擎,是由Python实现的模板语言,Jinja2 的作者也是 Flask 的作者。他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
Fullcalendar日历使用,包括视图选择、事件插入、编辑事件、事件状态更改、事件添加和删除、事件拖动调整,自定义头部,加入el-popover显示图片、图片预览、添加附件链接等,支持手机显示。
监听QQ消息并不需要我们写代码,因为市面上已经有很多开源QQ机器人框架,在这里我们使用go-cqhttp官方文档:go-cqhttp如果您感兴趣的话,可以阅读一下官方文档,如果不想看,直接看我的文章即可。
【Flask框架】—— 视图和URL总结
python+web+flask轻量级框架的实战小项目。登录功能,后续功能可自行丰富。
有了这个就可以配置可信IP,关键是不需要企业认证,个人信息就可以做。
本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。 本人经验,学习一门语言或框架时,请首先阅读官方文档。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。
本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。基础薄弱的同学请戳Flask官方文档教程 本人经验,学习一门语言或框架时,请首先阅读官方文档。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。 如果python都完全不熟悉,一定不要着急学习框架,请首先学习python官方文档,一步一个脚印。要不然从入门到放弃是大概率事件。 Python 官方文档教程
快到年末了 相信大家都在忙着处理年末数据 刚好有一个是对超市的商品库存进行分析的学员案例 真的非常简单~
一个简易的问答系统就这样完成了,当然,这个项目还可以进一步完善,比如 将数据存入Elasticsearch,通过它先进行初步的检索,然后再通过这个系统,当然我们也可以用其他的架构实现。如果你对这系统还有其他的疑问,也可以再下面进行留言!!!
#模版继承和页面之间的调用@app.route(&quot;/bl&quot;)def bl(): return render_template(&quot;file_2.html&quot;)主ht
#form表达提交@app.route(&quot;/data&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;]) #methods 让当前路由支持GET 和
#form表达提交@app.route(&quot;/data&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;]) #methods 让当前路由支持GET 和
#session 使用app.secret_key = &quot;dsada12212132dsad1232113&quot;app.config[&#39;PERMANENT_SESSION_LI
#文件上传@app.route(&quot;/file&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;])def file(): if request.meth
#跳转操作:redirect@app.route(&quot;/red&quot;)def red(): return redirect(&quot;/login&quot;)
#session 使用app.secret_key = &quot;dsada12212132dsad1232113&quot;app.config[&#39;PERMANENT_SESSION_LI
@app.route(&quot;/req&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;])def req(): print(request.headers)
#模版继承和页面之间的调用@app.route(&quot;/bl&quot;)def bl(): return render_template(&quot;file_2.html&quot;)主ht
#文件操作:send_file,支持图片 视频 mp3 文本等@app.route(&quot;/img&quot;)def img(): return send_file(&quot;1.jpg&q