python_web学习笔记七:flask基础篇

一、工程搭建

1.环境搭建

mkvirtualenv flask -p python3
pip install flask==1.0.2

2.第一个程序helloworld

from flask import Flask

# 创建flask对象
app = Flask(__name__)


# 使用app对象的route装饰器装饰视图函数
@app.route('/')
def index():
    return 'hello world'


# 调用app.run方法
if __name__ == '__main__':
    app.run()

  • 一些初始化的参数

import_name=__name__, # 表示导入该模块的名字, 给Flask寻找静态资源使用的。直接使用__name__。
static_folder='my_static', # 设置静态资源的存放目录,默认是 static
static_url_path='/static_tmp', # 表示访问静态资源的前缀路由,默认是 '/' + static_folder
template_folder='templates' # 存放模板的文件夹, 默认值就是 templates

3.常用的三种加载配置的方式

from flask import Flask

app = Flask(__name__)


# 加载配置
# 1.使用类加载配置(方便)
class Config(object):
    REDIS1 = "redis://127.0.0.1/1"


app.config.from_object(Config)
print(app.config.get("REDIS1"))
# 2.从配置文件加载(安全)
# app.config.from_pyfile("02_config.ini")
# print(app.config.get("REDIS2"))
# 3.从环境变量加载,本质是从配置文件中加载(灵活、安全)
# silent: False 表示不安静处理,如果找不到环境变量,会抛出异常。默认是False
# silent: True 表示安静处理,如果找不到环境变量,不会抛出异常。
# 注意:环境变量对应值为配置文件的文件名,不然读取不到
app.config.from_envvar("FLASK_CONFIG", silent=True)
print(app.config.get("REDIS2"))
if __name__ == '__main__':
    app.run()

4.实际开发中常用加载方式

from flask import Flask


def create_app(config):
    app = Flask(__name__)
    # 1.从配置类中加载配置
    app.config.from_object(config)
    # 2.从环境变量中加载配置
    app.config.from_envvar("REDIS2", silent=True)
    return app


class Config(object):
    REDIS1 = "redis://127.0.0.1/1"


app = create_app(Config)
print(app.config.get("REDIS1"))
print(app.config.get("REDIS2"))

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

5.app.run参数

from flask import Flask

app = Flask(__name__)


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


if __name__ == '__main__':
    # 1.host 绑定的ip地址
    # 2.port 监听的端口号
    # 3.debug 是否开启调试模式
    # 开始调试模式后,保存自动重启,把错误显示在页面上,方便调试
    app.run(host='0.0.0.0', port=5001, debug=True)

6.终端启动方式

# 1.设置环境变量
export FLASK_APP=app所在模块
export FLASK_ENV=development  # 表示运行在开发模式,生产模式production
# 2.运行
flask run -h 0.0.0.0 -p 5001

二、路由与蓝图

1.查询路由的三种方式

from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    # 3.自定义一个接口
    data = {}
    for rule in app.url_map.iter_rules():
        data[rule.endpoint] = rule.rule
    return jsonify(data)


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


# 1.直接打印url_map
print(app.url_map)
# 2.终端运行时
# flask routes 模块名

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

2.指定请求方式

from flask import Flask

app = Flask(__name__)


@app.route('/', methods=["GET"])
def index():
    return 'index'


@app.route('/index2', methods=["POST"])
def index2():
    return 'index2'


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

3.允许跨域

  • 安装

    pip install falsk-cors
    
  • 使用

    from flask import Flask
    # 导入
    from flask_cors import CORS
    
    app = Flask(__name__)
    # 允许跨域
    CORS(app)
    
    
    @app.route('/')
    def index():
        return 'index'
    
    
    if __name__ == '__main__':
        app.run()
    

4.蓝图基本使用

from flask import Flask, Blueprint

app = Flask(__name__)
# 1.创建蓝图对象
bp = Blueprint("user", __name__)


# 2.用蓝图对象装饰
@bp.route('/')
def index():
    return 'index'


# 3.注册
app.register_blueprint(bp)
if __name__ == '__main__':
    app.run()

5.把蓝图抽离成包

  • main.py

    from user import user_bp
    from flask import Flask
    
    app = Flask(__name__)
    # 注册
    app.register_blueprint(user_bp)
    
    if __name__ == '__main__':
        app.run()
    
  • user/__init__.py

    from flask import Blueprint
    
    # 创建蓝图
    user_bp = Blueprint("user", __name__)
    from . import views
    
  • user/views.py

    from user import user_bp
    
    
    # 使用蓝图对象装饰
    @user_bp.route("/")
    def index():
        return "index"
    

6.蓝图的一些参数

# user/__init__.py
# name: 蓝图对象名字,在同一个app中,不能有相同名称的蓝图对象
# import_name: __name__
# static_url_path: 蓝图自己的静态资源路由
# static_folder: 蓝图自己的静态资源文件夹
# template_folder: 蓝图自己的模板文件夹

# 使用url_prefix指定蓝图对象url前缀
app.register_blueprint(user_bp, url_prefix='/user')

注意:
  如果蓝图模板文件夹中有和app模板文件夹中同名的模板文件,会优先返回app中的模板文件。

三、请求与响应

1.处理请求

a.路径传参

from flask import Flask

app = Flask(__name__)


@app.route('/<user_id>')
def index(user_id):
    return 'user_id is %s' % user_id


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

b.常用的转换器

from flask import Flask

app = Flask(__name__)


@app.route('/str/<string:param>')
def string_view(param):
    return 'param is %s' % param


@app.route('/int/<int:param>')
def int_view(param):
    return 'param is %s' % param


@app.route('/float/<float:param>')
def float_view(param):
    return 'param is %s' % param


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

c.自定义转换器

from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 1.自定义自己的转换器类
class Mobile(BaseConverter):
    # 匹配手机号
    regex = r"1[3-9]\d{9}"


# 2.添加
app.url_map.converters["mobile"] = Mobile

# 3.使用
@app.route('/<mobile:param>')
def index(param):
    return 'param is %s' % param


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

d.request对象获取参数

from flask import Flask, request, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    # 查询字符串
    # data = request.args.get("name")
    # 表单
    # data = request.form.get("name")
    # 原始数据
    # data = request.data
    # json数据
    # data = jsonify(request.json)
    # files数据
    # data = request.files.get("a")
    # headers头
    # data = request.headers.get("name")
    # url路由
    # data = request.url
    # method请求方法
    data = request.method
    return data


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

2.处理响应

a.返回响应

from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
    # 1.直接返回
    return 'index'


@app.route('/index2')
def index2():
    # 2.构建响应对象
    response = make_response("index2")
    return response


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

b.返回自定义状态码和头部

from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
    # 1.以元组的方式返回
    return 'index', 201, {"name": "lw"}


@app.route('/index2')
def index2():
    # 使用响应对象设置
    response = make_response("index2")
    response.status_code = 404
    response.headers["age"] = 18
    return response


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

c.返回json数据

import json

from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    data = {
        "name": "lw",
        "age": 18
    }
    # 1.使用json模块
    return json.dumps(data), 200, {"Content-Type": "application/json"}


@app.route("/2")
def index2():
    data = {
        "qq": '123'
    }
    # 2.字典参数
    return jsonify(data)


@app.route("/3")
def index3():
    # 3.关键字参数
    return jsonify(tel="13245")


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

d.返回jinja2模板

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    response = render_template("user/render.html", name="laowang", age=18)
    return response


if __name__ == '__main__':
    app.run()
  • render.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{ name }}</h1>
    <h1>{{ age }}</h1>
</body>
</html>

e.重定向

from flask import Flask, redirect

app = Flask(__name__)


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


@app.route('/index2')
def index2():
    return redirect("https://www.baidu.com")


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

3.cookie与session

a.cookie

from flask import Flask, make_response, request

app = Flask(__name__)

# 设置cookie
@app.route('/set_cookie/<name>')
def set_cookie(name):
    # 构造响应对象
    response = make_response("set_cookie")
    # max_age用户设置cookie有效期,单位秒
    response.set_cookie("name", name)
    return response


# 获取cookie
@app.route('/get_cookie')
def get_cookie():
    name = request.cookies.get("name")
    return "cookie is %s" % name

# 删除cookie
@app.route('/delete_cookie')
def delete_cookie():
    # 相当于把max_age设置为0
    response = make_response("delete_cookie")
    response.delete_cookie("name")
    return response


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

b.session

from flask import Flask, session

app = Flask(__name__)
# 设置secret_key
app.secret_key = "asdgdg"
# 设置session
@app.route('/set_session/<name>')
def set_session(name):
    session['name'] = name
    return 'index'

# 获取session
@app.route('/get_session')
def get_session():
    name = session.get("name")
    return str(name)


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

四、请求钩子与上下文

1.异常处理

a.abort的使用

from flask import Flask, abort

app = Flask(__name__)


@app.route('/')
def index():
    # 抛出异常
    abort(404)
    return 'index'


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

b.异常捕获处理

from flask import Flask, abort

app = Flask(__name__)


@app.errorhandler(404)
def func_404(e):
    return "这是一个漂亮的404页面", 404


@app.errorhandler(ZeroDivisionError)
def func_0(e):
    return "0除异常", 502


@app.route('/')
def index():
    # 1/0
    abort(404)
    return 'index'


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

2.请求钩子

a.基本使用

from flask import Flask

app = Flask(__name__)

# 在所有请求开始前执行一次
@app.before_first_request
def before_first_request():
    print("before_first_request")

# 在所有请求开始前执行
@app.before_request
def before_request():
    print("before_request")

# 在所有请求,视图函数执行完后执行
@app.after_request
def after_request(response):
    print("after_request")
    return response

# 在钩子后执行
@app.teardown_request
def teardown_request(e):
    print("teardown_request")


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


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


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

b.认证示例

from flask import Flask, request, session, jsonify, g

app = Flask(__name__)
# 两种设置方式
app.secret_key = "fdasdgf"
# app.config["SECRET_KEY"] = "QERWEFD"

# 准备用户
users = [
    {"user_id": 1, "username": "laowang", "password": "123456"}
]


# 登录接口
@app.route('/login')
def login():
    username = request.args.get("username")
    password = request.args.get("password")
    for user in users:
        if username == user["username"] and password == user["password"]:
            # 登录成功
            session["user_id"] = user["user_id"]
            return "登录成功"
    return '登录失败'


@app.before_request
def before_request():
    user_id = session.get("user_id")
    if user_id is None:
        g.user = None
    else:
        for user in users:
            if int(user_id) == user["user_id"]:
                # 如果找到用户
                g.user = user


# 使用装饰器继续优化视图函数代码
# 强制登录装饰器
def login_required(func):
    def wrapper(*args, **kwargs):
        # 检测
        if g.user is None:
            return "请先登录"
        else:
            return func(*args, **kwargs)
    return wrapper


@app.route("/user_info")
@login_required
def user_info():
    return jsonify(g.user)


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

3.上下文

a.current_app:指向处理当前请求的app对象

from flask import Flask, current_app

app = Flask(__name__)


class Config(object):
    REDIS = "redis://192.168.230.128:6379/1"


app.config.from_object(Config)
print(app.config.get("REDIS"))


@app.route('/')
def index():
    # current_app指向处理当前请求的app,它是一个代理
    return current_app.config.get("REDIS")

# 蓝图
from user import user_bp

app.register_blueprint(user_bp, url_prefix="/user")

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

b. g:临时的全局变量,用于参数传递

from flask import Flask, g

app = Flask(__name__)


@app.before_request
def before_request():
    g.user_id = 123


def func1():
    print(g.user_id)


@app.route('/')
def index():
    func1()
    return str(g.user_id)


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

c.测试

from flask import Flask, current_app, g, request, session

app = Flask(__name__)


def test_request_context():
    print(request)
    print(session)
    print(g)
    print(current_app)


@app.route('/')
def index():
    # 1.正常请求可以使用
    test_request_context()
    return 'index'


if __name__ == '__main__':
    # 在上下文外面,不能使用,会直接抛出异常
    # test_request_context()
    # app.run(host='192.168.230.128', debug=True)
    # 2.构建测试请求上细纹对象
    # environ = {'wsgi.version': (1, 0), 'wsgi.input': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/',
    #            'SERVER_NAME': 'baidu server', 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80'}  # 模拟解析客户端请求之后的wsgi字典数据
    # with app.request_context(environ):
    #     # 构建了一个请求上下文环境,4个对象都可用
    #     test_request_context()

    # 3.构建应用上下文对象
    with app.app_context():
        print(current_app)
        print(g)
        # 请求上下文对象不可用
        # print(request)

五、Flask-RESTful

1.起步

pip install flask-restful
from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)

# 1.创建API对象
api = Api(app)


# 2.定义视图类
class HelloWorldResource(Resource):
    def get(self):
        return {"msg": "hello world"}

    def post(self):
        return {"msg": "hello world"}


# 3.使用api对象绑定视图类和路由
api.add_resource(HelloWorldResource, "/")

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

2.蓝图中使用flask-restful

from flask import Flask, Blueprint
from flask_restful import Resource, Api

app = Flask(__name__)
# 1.创建蓝图对象
user_bp = Blueprint("user", __name__)

# 2.创建api对象
api = Api(user_bp)


# 3.定义视图类
class UerInfoResource(Resource):
    def get(self):
        return {"msg": "user_info"}


# 4.使用api对象绑定视图类和路由的关系
api.add_resource(UerInfoResource, "/", endpoint='userinfo')
# 5.把蓝图对象注册到app中
app.register_blueprint(user_bp)

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

3.类视图使用装饰器的方式

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)


def decorator1(func):
    def wrapper(*args, **kwargs):
        print("decorator1")
        return func(*args, **kwargs)

    return wrapper


def decorator2(func):
    def wrapper(*args, **kwargs):
        print("decorator2")
        return func(*args, **kwargs)

    return wrapper


api = Api(app)


class Index(Resource):
    # 1.列表的方式,所有的请求方式都会受到影响
    # method_decorators = [decorator1, decorator2]
    # 2.字典的方式
    method_decorators = {
        "get": [decorator1, decorator2],
        "post": [decorator1],
    }

    def get(self):
        return {"msg": "get"}

    def post(self):
        return {"msg": "post"}


api.add_resource(Index, '/')

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

4.使用RequestParser获取参数

from flask import Flask, request
from flask_restful import Resource, Api
from flask_restful.reqparse import RequestParser
from flask_restful.inputs import int_range
import re

app = Flask(__name__)
api = Api(app)


def mobile(mobile_str):
    if re.match(r"^1[3-9]\d{9}$", mobile_str):
        return mobile_str
    else:
        raise ValueError("%s is not a mobile" % mobile_str)


class Index(Resource):
    def get(self):
        # 1.创建RequestParser对象
        parser = RequestParser()
        # 2.添加需要解析的参数
        parser.add_argument("a")
        # 3.调用parse_args解析参数
        req = parser.parse_args()
        # 4.直接使用
        return {"a": req.get("a")}

        # # 也可以用原来的request对象获取参数
        # a = request.args.get("a")
        # return {"a": a}

    def post(self):
        parser = RequestParser()
        parser.add_argument(
            "a",  # 参数的名称
            location=["args", "form"],  # 描述该参数出现的位置
            required=True,  # 请求是否一定要携带对应参数。True必须,False不必
            # help="missing a param",  # 自定义提示
            action="append",  # 同名参数处理方式,默认store,保留第一个。append则添加
            # type=int,  # 匹配参数类型
            # type=int_range(1, 10)
            type=mobile
        )
        req = parser.parse_args()
        return {"a": req.get("a")}


api.add_resource(Index, "/")

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

5.marshal工具

from flask import Flask
from flask_restful import Resource, Api, fields, marshal_with, marshal

app = Flask(__name__)
api = Api(app)


# 模拟模型类
class User(object):
    def __init__(self, user_id, name, age):
        self.user_id = user_id
        self.name = name
        self.age = age


# 定义需要返回的数据格式
my_fields = {
    "user_id": fields.Integer,
    "name": fields.String,
    "age": fields.Integer
}


class UserInfo(Resource):
    # 1.使用装饰器的方式
    @marshal_with(my_fields, envelope="data")
    def get(self):
        user = User(1, "laowang", 18)
        # data = {
        #     "user_id": user.user_id,
        #     "name": user.name,
        #     "age": user.age,
        # }
        return user
    # def get(self):
    #     # 2.以函数的方式
    #     user = User(1, "laowang", 20)
    #     return marshal(user, my_fields, envelope="data")


api.add_resource(UserInfo, "/user_info")
if __name__ == '__main__':
    app.run()

6.修改最终返回的JSON数据格式

  • 原生的做法
import json

from flask import Flask, jsonify

app = Flask(__name__)


@app.after_request
def after_request(response):
    data = json.loads(response.data.decode())
    if "message" not in data:
        data = {
            "message": "ok",
            "data": data
        }
    response.data = json.dumps(data)
    return response


@app.route('/user_name')
def user_name():
    data = {
        "name": "laowang"
    }
    return jsonify(data)


@app.route('/user_age')
def user_age():
    data = {
        "message": "ok",
        "data": {
            "age": 18
        }
    }
    return jsonify(data)


if __name__ == '__main__':
    app.run()
  • Flask-RESTful的做法
import json

from flask import Flask, make_response, current_app
from flask_restful import Resource, Api
from flask_restful.utils import PY3

app = Flask(__name__)
api = Api(app)


# 普通的做法
# @api.representation("application/json")
# def representation(data, code, headers):
#     if "message" not in data:
#         data = {
#             "message": "ok",
#             "data": data
#         }
#     response = make_response(json.dumps(data))
#     response.status_code = code
#     response.headers.extend(headers)
#     return response

# 建议做法
@api.representation("application/json")
def output_json(data, code, headers=None):
    if "message" not in data:
        data = {
            "message": "ok",
            "data": data
        }
    settings = current_app.config.get('RESTFUL_JSON', {})

    if current_app.debug:
        settings.setdefault('indent', 4)
        settings.setdefault('sort_keys', not PY3)
    dumped = json.dumps(data, **settings) + "\n"
    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp


class UserInfo(Resource):
    def get(self):
        return {"age": 18}


api.add_resource(UserInfo, "/")

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

六、curl命令

curl -X http请求方式 请求的路径url -H 请求头字段 -d 请求体数据
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值