您当前的位置: 首页 >  flask

IT之一小佬

暂无认证

  • 0浏览

    0关注

    1192博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Flask框架中路由请求处理

IT之一小佬 发布时间:2021-08-05 19:17:50 ,浏览量:0

        在视图编写中需要读取客户端请求携带的数据时,如何才能正确的取出数据呢?请求携带的数据可能出现在HTTP报文中的不同位置,需要使用不同的方法来获取参数。

1、获取url路径上的数据

示例代码:

from flask import Flask, jsonify

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False

books = [
    {"id": 1, "name": '三国演义'},
    {"id": 2, "name": '水浒传'},
    {"id": 3, "name": '西游记'},
    {"id": 4, "name": '红楼梦'},
]


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/books/list')
def book_list():
    # return books  # 直接返回books会报错的,类型格式不支持
    return jsonify(books)


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

运行结果:

示例代码:

from flask import Flask, jsonify

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False

books = [
    {"id": 1, "name": '三国演义'},
    {"id": 2, "name": '水浒传'},
    {"id": 3, "name": '西游记'},
    {"id": 4, "name": '红楼梦'},
]


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/books/list')
def book_list():
    # return books  # 直接返回books会报错的,类型格式不支持
    return jsonify(books)


@app.route('/book/')
def book_detail(book_id):
    for book in books:
        if book_id == book['id']:
            return book
    return f"id:{book_id}的图书不存在!"


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

运行结果:

2、URL路径参数(动态路由)

例如,有一个请求访问的接口地址为/users/123,其中123实际上为具体的请求参数,表明请求123号用户的信息。此时如何从url中提取出123的数据?

Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器语法:

@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)

示例代码:

from flask import Flask

app = Flask(__name__)


@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)


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

运行效果:

        此处的即是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配、并以字符串为数据类型类型、 user_id为参数名传入视图。

Flask也提供其他类型的转换器

        ,尖括号是固定写法,语法为,variable默认的数据类型是字符串。如果需要指定类型,则要写成,其中converter就是类型名称,可以有以下几种:

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}
  • string: 默认的数据类型,接受没有任何斜杠/的字符串。
  • int: 整形
  • float: 浮点型。
  • path: 和string类似,但是可以传递斜杠/。
  • uuid: uuid类型的字符串。
  • any:可以指定多种路径。

将上面的例子以整型匹配数据,可以如下使用:

@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)


@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)

示例代码1:

from flask import Flask

app = Flask(__name__)


@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)


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

运行效果:

示例代码2:

from flask import Flask

app = Flask(__name__)


@app.route('/users/')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)


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

运行效果:

自定义转换器

        如果遇到需要匹配提取/sms_codes/18512345678中的手机号数据,Flask内置的转换器就无法满足需求,此时需要自定义转换器。

自定义转换器主要做3步

  1. 创建转换器类,保存匹配时的正则表达式

    from werkzeug.routing import BaseConverter
    
    class MobileConverter(BaseConverter):
        """
        手机号格式
        """
        regex = r'1[3-9]\d{9}'
    
    • 注意regex名字固定
  2. 将自定义的转换器告知Flask应用

    app = Flask(__name__)
    
    # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
    app.url_map.converters['mobile'] = MobileConverter
    
  3. 在使用转换器的地方定义使用

    @app.route('/sms_codes/')
    def send_sms_code(mob_num):
        return 'send sms code to {}'.format(mob_num)
    

示例代码:

from flask import Flask
from werkzeug.routing import BaseConverter


class MobileConverter(BaseConverter):
    """手机号格式"""
    regex = r'1[3-9]\d{9}'


app = Flask(__name__)

# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter


@app.route('/sms_codes/')
def send_code(mob_num):
    return 'send sms code to {}'.format(mob_num)


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

运行效果:

any路由示例方法:

from flask import Flask, jsonify

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('//')
def item(url_path):
    return f'I am {url_path}'


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

        在上面例子中,item这个函数可以接受两个URL,一个是/article/,另一个是/blog/。注意一定要传url_path参数,当然这个url_path的名称可以随便。

3、 其他参数

        如果不想定制子路径来传递参数,也可以通过传统的?=的形式来传递参数,例如:/article?id=xxx。如果想要获取其他地方传递的参数,可以通过Flask提供的request对象来读取。

不同位置的参数都存放在request的不同属性中

属性说明类型data记录请求的数据,并转换为字符串*form记录请求中的表单数据MultiDictargs记录请求中的查询参数MultiDictcookies记录请求中的cookie信息Dictheaders记录请求中的报文头EnvironHeadersmethod记录请求使用的HTTP方法GET/POSTurl记录请求的URL地址stringfiles记录请求上传的文件*

例如 想要获取请求/articles?channel_id=1channel_id的参数,可以按如下方式使用:

from flask import request

@app.route('/articles')
def get_articles():
    channel_id = request.args.get('channel_id')
    return 'you wanna get articles of channel {}'.format(channel_id)

示例代码:

from flask import Flask, request

app = Flask(__name__)


@app.route('/articles')
def get_articles():
    channel_id = request.args.get('channel_id')
    return 'you wanna get articles of channel {}'.format(channel_id)


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

运行效果:

上传图片

客户端上传图片到服务器,并保存到服务器中

from flask import request

@app.route('/upload', methods=['POST'])
def upload_file():
    f = request.files['pic']
    # with open('./demo.png', 'wb') as new_file:
    #     new_file.write(f.read())
    f.save('./demo.png')
    return 'ok'

 示例代码:

from flask import Flask, request

app = Flask(__name__)


@app.route('/upload', methods=['POST'])
def upload_file():
    f = request.files['pic']
    # with open('./demo.png', 'wb') as new_file:
    #     new_file.write(f.read())
    f.save('./demo.png')
    return 'ok'


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

【with open 和f.save效果是一样的,f.save是封装好的方法】

postman上传图片测试:

 

其它参数中分别get()和getlist()方法:

# 源码介绍 
   def get(self, key, default=None, type=None):
        """Return the default value if the requested data doesn't exist.
        If `type` is provided and is a callable it should convert the value,
        return it or raise a :exc:`ValueError` if that is not possible.  In
        this case the function will return the default as if the value was not
        found:

        >>> d = TypeConversionDict(foo='42', bar='blub')
        >>> d.get('foo', type=int)
        42
        >>> d.get('bar', -1, type=int)
        -1

        :param key: The key to be looked up.
        :param default: The default value to be returned if the key can't
                        be looked up.  If not further specified `None` is
                        returned.
        :param type: A callable that is used to cast the value in the
                     :class:`MultiDict`.  If a :exc:`ValueError` is raised
                     by this callable the default value is returned.
        """
源码介绍:
    def getlist(self, key, type=None):
        """Return the list of items for a given key. If that key is not in the
        `MultiDict`, the return value will be an empty list.  Just like `get`,
        `getlist` accepts a `type` parameter.  All items will be converted
        with the callable defined there.

        :param key: The key to be looked up.
        :param type: A callable that is used to cast the value in the
                     :class:`MultiDict`.  If a :exc:`ValueError` is raised
                     by this callable the value will be removed from the list.
        :return: a :class:`list` of all the values for the key.
        """

示例代码:

main.py

from flask import Flask, request, render_template

app = Flask(__name__)


@app.route('/register', methods=['GET', 'POST'])  # 支持get、post请求
def register():  # 视图函数
    if request.method == 'GET':  # 请求方式是get
        return render_template('register.html')  # 返回模板
    elif request.method == 'POST':
        name = request.form.get('name')  # form取post方式参数
        age = request.form.get('age')
        hobby = request.form.getlist('hobby')  # getlist取一键多值类型的参数
        # hobby = request.form.get('hobby')  # get只能获取到多个值中的第一个
        return "姓名:%s 年龄:%s 爱好:%s" % (name, age, hobby)


app.config['DEBUG'] = True

if __name__ == '__main__':
    # 0.0.0.0代表任何能代表这台机器的地址都可以访问
    app.run(host='0.0.0.0', port=5000)  # 运行程序

register.html




    
    register



    用户名:
    年龄:
    爱好:吃
    喝
    玩
    乐
    


运行效果:

 参考博文:

Python Flask中Request请求_zhangvalue的博客-CSDN博客_request.form.getlist

关注
打赏
1665675218
查看更多评论
立即登录/注册

微信扫码登录

0.0466s