Flask-01-安装、创建flask项目、路由的基本定义、http的请求与响应

Flask

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

Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。

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

官网: https://flask.palletsprojects.com/en/1.1.x/
官方文档: http://docs.jinkan.org/docs/flask/

Flask常用第三方扩展包:

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

可以通过 https://pypi.org/search/?c=Framework+%3A%3A+Flask 查看更多flask官方推荐的扩展

一、准备

mkvirtualenv flask -p python3

二、安装

pip install flask==0.12.5

三、创建flask项目

与django不同,flask不会提供任何的自动操作,所以需要手动创建项目目录,需要手动创建启动项目的管理文件

创建一个flask框架的主程序。名字可以是app.py/run.py/main.py/index.py

from flask import Flask

app = Flask(__name__)


@app.route("/")
def index():
    return "<h1>python31</h1>"


if __name__ == '__main__':

    app.run()
1.flask基本运行
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模块提供的

2.flask快速使用
from flask import Flask

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

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


if __name__ == '__main__':
    # 启动项目,不要在run 后面写任何代码,不会被执行到
    app.run(debug=True, port=8000, host='0.0.0.0')  
3.flask加载配置
from flask import Flask

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

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

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

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


if __name__ == '__main__':

    app.run() 

四、路由的基本定义

路由和视图的名称必须全局唯一,不能出现重复,否则报错。
url中可以传递路由参数, 2种方式
路由参数就是url路径的一部分。

1.任意路由参数接收
from flask import Flask

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

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

app.config.from_object(Config)


# 路由: 一种访问地址[url]和应用程序[视图]进行一对一绑定的映射关系
# 往往在开发中,我们所说的路由,其实通常指代完成路由绑定关系的路由类
@app.route(rule="/user/<user_id>-<mobile>")  # 可以指定一个或多个参数进行传递
def index(user_id, mobile):  # 这里的参数名称必须和路由上面的保持一致
    return "user_id=%s,mobile=%s" % (user_id, mobile)


if __name__ == '__main__':

    app.run()

2.限定路由参数接收

通过路由转换器限定路由参数的类型,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="/", methods=['get'])
def index():
    return "<h1>hello flask</h1>"


@app.route(rule="/user/<float:user_id>")  # 使用flask内置的路由参数转换器限定参数的类型,int, flask, string ....
def user(user_id):
    print(user_id)
    return "<h1>hello user</h1>"


if __name__ == '__main__':

    app.run()

3.自定义路由参数转换器

也叫正则匹配路由参数.

在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问

具体实现步骤为:

  • 导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录
  • 自定义转换器:自定义类继承于转换器基类
  • 添加转换器到默认的转换器字典中
  • 使用自定义转换器实现自定义匹配规则

当前此处定义的规则是:手机号码
代码:

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()

4.自定义转换器
from flask import Flask

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

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

app.config.from_object(Config)

# 自定义路由转换器
# 1. 声明的路由转换器类必须直接或间接继承于BaseConverter
from werkzeug.routing import BaseConverter

class MobileConverter(BaseConverter):
    # 2. 必须在初始化中调用父类对象进行初始化
    def __init__(self, *args, **kwargs):
        # 3. regex必须有参数
        self.regex = r'1[3-9]\d{9}'
        super().__init__(*args, **kwargs)

# 4. 注册
# app.url_map.converters['使用别名'] = 转换器类名
app.url_map.converters['mob'] = MobileConverter

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


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

5.路由限定请求方式
from flask import Flask

app = Flask(__name__)


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


if __name__ == '__main__':
    app.run(debug=True)
6.注册路由和视图代码进行分离处理
from flask import Flask

app = Flask(__name__)


def index():
    return "ok"

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

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

五、http的请求与响应

1.请求

文档: 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_stringMultiDict
cookies记录请求中的cookie信息Dict
headers记录请求中的请求头EnvironHeaders
method记录请求使用的HTTP方法GET/POST
url记录请求的URL地址string
files记录请求上传的文件列表*
json记录ajax请求的json数据json
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)

请求中的html表单数据

from flask import Flask, request

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)

来自客户端请求的其他数据


from flask import Flask, request

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"])  # boy
    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)

2.响应

flask默认支持2种响应方式:
数据响应: 默认响应html文本,也可以返回 JSON格式,或其他格式
页面响应: 重定向
​   url_for 视图之间的跳转
响应的时候,flask也支持自定义http响应状态码

from flask import Flask

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

# 编写视图和路由
from flask import make_response, jsonify, request
@app.route(rule='/user', methods=['get', 'post'])
def user():
    # 返回html文本
    # 默认直接可以通过return直接返回html文本格式
    # return "<h1>hello user</h1>"
    # return make_response('<h1>hello user</h1>')  # 等同于上面的一段

    # 返回json数据
    # data = {"username":"小明","age":17,"sex": True}

    # 识别身份
    if request.args.get('user') == 'abc':
        # 也可以返回图片,压缩包 等其他在浏览器能支持的数据,既可以支持显示图片,也可以支持显示
        with open('2.jpg', 'rb') as f:
            content = f.read()
            response = make_response(content)
            response.headers['Content-Type'] = 'image/jpeg'
            return response

    else:
        return '没有权限'

    # 支持下载
    # with open('123.zip', 'rb') as f:
    #     response.headers['Content-Type'] = 'application/zip'
    #     return response

@app.route('/')
def index():
    return "<img src='user?user=abc'>"


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

页面响应和自定义响应

from flask import Flask, redirect, url_for

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

# 编写视图和路由
# redirect 实际上就是Response响应类的实例对象
from flask import make_response
@app.route(rule='/')
def index():
    # 页面跳转
    # return redirect('http://www.baidu.com')  # 跳转到站外
    # return redirect('/user')  # 跳转到站内
    # return redirect(url_for('user', user_id=100))  # 通过url_for指定视图名称,直接找到对应路由进行跳转

    # 跳转的原理,实际就是利用HTML文档中的元信息
    response = make_response()
    response.headers['Location'] = "http://www.baidu.com"
    response.headers['Company'] = 'boy'  # 自定义响应头
    response.status_code = 302  # 自定义响应状态码
    return response

@app.route('/user12344')
def user():
    return "用户中心"


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

重定向跳转


from flask import Flask, redirect, url_for

app = Flask(__name__)

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

# 转内跳转,进行视图之间的跳转
@app.route('/')
def home():
    # 视图之间的跳转
    return redirect(url_for('index', name='xiaoming'))

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

if __name__ == '__main__':
    app.run(debug=True)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值