详细的Python Flask的操作

2023-11-20

本篇文章是Python Flask 建站框架入门课程_编程实战微课_w3cschool微课的学习笔记,根据课程整理而来,本人使用版本如下:

Python 3.10.0
Flask 2.2.2

简介

  • Flask是一个轻量级的可定制的web框架

  • Flask 可以很好地结合MVC模式进行开发

  • Flask还有很强的很强的扩展性和兼容性

核心函数库

Flask主要包括Werkzeug和Jinja2两个核心函数库,它们分别负责业务处理和安全方面的功能,这些基础函数为web项目开发过程提供了丰富的基础组件。

Werkzeug

Werkzeug库十分强大,功能比较完善,支持URL路由请求集成,一次可以响应多个用户的访问请求;

支持Cookie和会话管理,通过身份缓存数据建立长久连接关系,并提高用户访问速度;支持交互式Javascript调试,提高用户体验;

可以处理HTTP基本事务,快速响应客户端推送过来的访问请求。

Jinja2

Jinja2库支持自动HTML转移功能,能够很好控制外部黑客的脚本攻击;

系统运行速度很快,页面加载过程会将源码进行编译形成python字节码,从而实现模板的高效运行;

模板继承机制可以对模板内容进行修改和维护,为不同需求的用户提供相应的模板。

安装

通过pip安装即可

pip install Flask
# pip3
pip3 install Flask

目录结构

新项目创建后的结构

static文件夹:存放静态文件,比如css、js、图片等

templates文件夹:模板文件目录

app.py:应用启动程序

获取URL参数

列出所有URL参数

request.args.__str__()

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_world():  # put application's code here
    return request.args.__str__()


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

在浏览器中访问http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,将显示:

ImmutableMultiDict([('name', 'Loen'), ('age', ''), ('app', 'ios'), ('app', 'android')])

列出浏览器传给我们的Flask服务的数据

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_world():  # put application's code here

    # 列出访问地址
    print(request.path)

    # 列出访问地址及参数
    print(request.full_path)

    return request.args.__str__()


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

在浏览器中访问http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,控制台中显示

/
/?name=Loen&age&app=ios&app=android

获取指定的参数值

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_world():  # put application's code here

    return request.args.get('name')


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

在浏览器中访问http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,将显示:

Loen

处理多值

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_world():  # put application's code here
    r = request.args.getlist('app')  # 返回一个list
    return r


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

在浏览器中访问http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,将显示:

[
  "ios",
  "android"
]

获取POST方法传送的数据

作为一种HTTP请求方法,POST用于向指定的资源提交要被处理的数据。

我们在某些时候不适合将数据放到URL参数中,密或者数据太多,浏览器不一定支持太长长度的URL。这时,一般使用POST方法。

本文章使用python的requests库模拟浏览器。

安装命令:

pip install requests

看POST数据内容

app.py代码如下:

from flask import Flask, request

app = Flask(__name__)


@app.route('/register', methods=['POST'])
def register():
    print(request.headers)
    print(request.stream.read())
    return 'welcome'


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

register.py代码如下:

import requests

if __name__ == '__main__':
    user_info = {'name': 'Loen', 'password': 'loveyou'}
    r = requests.post("http://127.0.0.1:5000/register", data=user_info)
    print(r.text)

运行app.py,然后运行register.py

register.py将输出:

welcome

app.py将输出:

Host: 127.0.0.1:5000
User-Agent: python-requests/2.28.2
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 26
Content-Type: application/x-www-form-urlencoded


b'name=Loen&password=loveyou'
127.0.0.1 - - [14/Feb/2023 21:12:17] "POST /register HTTP/1.1" 200 -

解析POST数据

app.py代码如下:

from flask import Flask, request

app = Flask(__name__)


@app.route('/register', methods=['POST'])
def register():
    # print(request.stream.read()) # 不要用,否则下面的form取不到数据
    print(request.form)
    print(request.form['name'])
    print(request.form.get('name'))
    print(request.form.getlist('name'))
    print(request.form.get('nickname', default='little apple'))
    return 'welcome'


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

register.py代码不变,运行app.py,然后运行register.py

register.py将输出:

welcome

app.py将输出:

ImmutableMultiDict([('name', 'Loen'), ('password', 'loveyou')])
Loen
Loen
['Loen']
little apple

request.form会自动解析数据。

request.form[‘name’]和request.form.get(‘name’)都可以获取name对应的值。

request.form.get()可以为参数default指定值以作为默认值。

获取POST中的列表数据

app.py代码如下:

from flask import Flask, request

app = Flask(__name__)


@app.route('/register', methods=['POST'])
def register():
    # print(request.stream.read()) # 不要用,否则下面的form取不到数据
    print(request.form.getlist('name'))
    return 'welcome'


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

register.py代码如下:

import requests

if __name__ == '__main__':
    user_info = {'name': ['Loen', 'Alan'], 'password': 'loveyou'}
    r = requests.post("http://127.0.0.1:5000/register", data=user_info)
    print(r.text)

运行app.py,然后运行register.py

register.py将输出:

welcome

app.py将输出:

['Loen', 'Alan']

处理和响应JSON数据

处理JSON数据

如果POST的数据是JSON格式,request.json会自动将json数据转换成Python类型(字典或者列表)。

app.py代码如下:

from flask import Flask, request

app = Flask(__name__)


@app.route('/add', methods=['POST'])
def add():
    print(type(request.json))
    print(request.json)
    result = request.json['n1'] + request.json['n2']
    return str(result)


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

register.py代码如下:

import requests

if __name__ == '__main__':
    json_data = {'n1': 5, 'n2': 3}
    r = requests.post("http://127.0.0.1:5000/add", json=json_data)
    print(r.text)

运行app.py,然后运行register.py

register.py将输出:

8

app.py将输出:

<class 'dict'>
{'n1': 5, 'n2': 3}

响应JSON数据(Response)

app.py代码如下:

import json

from flask import Flask, request, Response

app = Flask(__name__)


@app.route('/add', methods=['POST'])
def add():
    result = {'sum': request.json['n1'] + request.json['n2']}
    return Response(json.dumps(result), mimetype='application/json')


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

register.py代码如下:

import requests

if __name__ == '__main__':
    json_data = {'n1': 5, 'n2': 3}
    r = requests.post("http://127.0.0.1:5000/add", json=json_data)
    print(r.headers)
    print(r.text)

运行app.py,然后运行register.py

register.py将输出:

/home/huangge1199/PycharmProjects/flaskProject/venv/bin/python /home/huangge1199/PycharmProjects/flaskProject/register.py 
{'Server': 'Werkzeug/2.2.2 Python/3.7.3', 'Date': 'Tue, 14 Feb 2023 13:37:49 GMT', 'Content-Type': 'application/json', 'Content-Length': '10', 'Connection': 'close'}
{"sum": 8}

响应JSON数据(jsonify)

app.py中app()返回时使用下面的内容,效果同之前一样

return jsonify(result)

上传表单

用 Flask 处理文件上传很简单,只要确保你没忘记在 HTML 表单中设置 enctype=“multipart/form-data” 属性,不然你的浏览器根本不会发送文件。

安装响应的库werkzeug

pip install werkzeug

目录结构:

app.py代码如下:

from flask import Flask, request
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)

# 文件上传目录
app.config['UPLOAD_FOLDER'] = 'static/uploads/'
# 支持的文件格式
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'}  # 集合类型


# 判断文件名是否是我们支持的格式
def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']


@app.route('/upload', methods=['POST'])
def upload():
    upload_file = request.files['image']
    if upload_file and allowed_file(upload_file.filename):  # 上传前文件在客户端的文件名
        filename = secure_filename(upload_file.filename)
        # 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名
        upload_file.save(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
        return 'info is ' + request.form.get('info', '') + '. success'
    else:
        return 'failed'


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

register.py代码如下:

import requests

if __name__ == "__main__":
    file_data = {'image': open('flask.png', 'rb')}
    user_info = {'info': 'flask'}
    r = requests.post("http://127.0.0.1:5000/upload", data=user_info, files=file_data)
    print(r.text)

运行app.py,然后运行register.py,这时候文件已经上传到了指定目录中

要控制上产文件的大小,可以设置请求实体的大小,代码如下:

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB

获取上传文件的内容,代码如下:

file_content = request.files['image'].stream.read()

Restful URL

Restful URL可以看做是对 URL 参数的替代

变量规则

写法如下:

@app.route('/user/<username>/friends')

转换类型

使用 Restful URL 得到的变量默认为str对象。我们可以用flask内置的转换机制,即在route中指定转换类型,写法如下:

@app.route('/page/<int:num>')

有3个默认的转换器:

  • int:接受整数

  • float:同 int ,但是接受浮点数

  • path:和默认的相似,但也接受斜线

自定义转换器

自定义的转换器是一个继承werkzeug.routing.BaseConverter的类,修改to_python和to_url方法即可。

to_python方法用于将url中的变量转换后供被@app.route包装的函数使用,to_url方法用于flask.url_for中的参数转换。

下面是一个示例:

from flask import Flask, url_for
from werkzeug.routing import BaseConverter


class MyIntConverter(BaseConverter):

    def __init__(self, url_map):
        super(MyIntConverter, self).__init__(url_map)

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return value * 2


app = Flask(__name__)
app.url_map.converters['my_int'] = MyIntConverter


@app.route('/page/<my_int:num>')
def page(num):
    print(num)
    print(url_for('page', num='145'))  # page 对应的是 page函数 ,num 对应对应`/page/<my_int:num>`中的num,必须是str
    return 'hello world'


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

运行app.py,浏览器访问http://127.0.0.1:5000/page/28后,app.py的输出信息是:

28
/page/145145

使用url_for生成链接

工具函数url_for可以让你以软编码的形式生成url,提供开发效率。

例子app.py代码如下:

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/')
def hello_world():
    pass


@app.route('/user/<name>')
def user(name):
    pass


@app.route('/page/<int:num>')
def page(num):
    pass


@app.route('/test')
def test():
    print(url_for('test'))
    print(url_for('user', name='loen'))
    print(url_for('page', num=1, q='welcome to w3c 15%2'))
    print(url_for('static', filename='uploads/flask.png'))
    return 'Hello'


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

运行app.py。然后在浏览器中访问http://127.0.0.1:5000/testserver.py控制台将输出以下信息:

/test
/user/loen
/page/1?q=welcome+to+w3c+15%252
/static/uploads/flask.jpg

使用redirect重定向网址

在浏览器中访问http://127.0.0.1:5000/old,浏览器的url会变成http://127.0.0.1:5000/new,并显示,app.py代码如下:

from flask import Flask, url_for, redirect

app = Flask(__name__)


@app.route('/old')
def old():
    print('this is old')
    return redirect(url_for('new'))


@app.route('/new')
def new():
    print('this is new')
    return 'this is new'


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

运行app.py,然后在浏览器中访问http://127.0.0.1:5000/old

浏览器显示:

this is new

控制台显示:

this is old
this is new

自定义404

处理HTTP错误

要处理HTTP错误,可以使用flask.abort函数。

app.py代码如下:

from flask import Flask, abort

app = Flask(__name__)


@app.route('/user')
def user():
    abort(401)  # Unauthorized 未授权
    print('Unauthorized, 请先登录')


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

运行app.py,然后在浏览器中访问http://127.0.0.1:5000/user

浏览器显示:

自定义错误页面

page_unauthorized 函数返回的是一个元组,401 代表HTTP 响应状态码。

如果省略401,则响应状态码会变成默认的 200。

app.py代码如下:

from flask import Flask, abort, render_template_string

app = Flask(__name__)


@app.route('/user')
def user():
    abort(401)  # Unauthorized


@app.errorhandler(401)
def page_unauthorized(error):
    return render_template_string('<h1> Unauthorized </h1><h2>{{ error_info }}</h2>', error_info=error), 401


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

运行app.py,然后在浏览器中访问http://127.0.0.1:5000/user

浏览器显示:

用户会话

session 用来记录用户的登录状态,一般基于cookie实现。

app.py代码如下:

from flask import Flask, render_template_string, request, session, redirect, url_for

app = Flask(__name__)

app.secret_key = 'LoenDSdtj\9bX#%@!!*(0&^%)'


@app.route('/login')
def login():
    page = '''
    <form action="{{ url_for('do_login') }}" method="post">
        <p>name: <input type="text" name="user_name" /></p>
        <input type="submit" value="Submit" />
    </form>
    '''
    return render_template_string(page)


@app.route('/do_login', methods=['POST'])
def do_login():
    name = request.form.get('user_name')
    session['user_name'] = name
    return 'success'


@app.route('/show')
def show():
    return session['user_name']


@app.route('/logout')
def logout():
    session.pop('user_name', None)
    return redirect(url_for('login'))


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

代码的含义

app.secret_key用于给session加密。

在/login中将向用户展示一个表单,要求输入一个名字,submit后将数据以post的方式传递给/do_login,/do_login将名字存放在session中。

如果用户成功登录,访问/show时会显示用户的名字。此时,打开调试工具,选择session面板,会看到有一个cookie的名称为session。

/logout用于登出,通过将session中的user_name字段pop即可。Flask中的session基于字典类型实现,调用pop方法时会返回pop的键对应的值;如果要pop的键并不存在,那么返回值是pop()的第二个参数。

另外,使用redirect()重定向时,一定要在前面加上return。

设置session的有效时间

设置session的有效时间设置为5分钟。

代码如下:

from datetime import timedelta
from flask import session, app

session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)

使用Cookie

Cookie是存储在客户端的记录访问者状态的数据。

常用的用于记录用户登录状态的session大多是基于cookie实现的。

cookie可以借助flask.Response来实现。

使用Response.set_cookie添加和删除cookie。

expires参数用来设置cookie有效时间,值可以是datetime对象或者unix时间戳。

res.set_cookie(key='name', value='loen', expires=time.time()+6*60)

上面的expire参数的值表示cookie在从现在开始的6分钟内都是有效的。

要删除cookie,将expire参数的值设为0即可:

res.set_cookie('name', '', expires=0)

详细的app.py代码如下:

import time

from flask import Flask, request, Response

app = Flask(__name__)


@app.route('/add')
def login():
    res = Response('add cookies')
    res.set_cookie(key='name', value='loen', expires=time.time() + 6 * 60)
    return res


@app.route('/show')
def show():
    return request.cookies.__str__()


@app.route('/del')
def del_cookie():
    res = Response('delete cookies')
    res.set_cookie('name', '', expires=0)
    return res


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

闪存系统 flashing system

Flask 的闪存系统(flashing system)用于向用户提供反馈信息,这些反馈信息一般是对用户上一次操作的反馈。

反馈信息是存储在服务器端的,当服务器向客户端返回反馈信息后,这些反馈信息会被服务器端删除。

详细的app.py代码如下:

import time

from flask import Flask, get_flashed_messages, flash

app = Flask(__name__)
app.secret_key = 'some_secret'


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


@app.route('/gen')
def gen():
    info = 'access at ' + time.time().__str__()
    flash(info)
    return info


@app.route('/show1')
def show1():
    return get_flashed_messages().__str__()


@app.route('/show2')
def show2():
    return get_flashed_messages().__str__()


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详细的Python Flask的操作 的相关文章

随机推荐

  • C# 如何将SPL文件转换成EMF文件

    本文主要讲述如何将SPL文件转换成EMF文件 目录 一 什么是SPL文件和EMF文件 一 SPL文件 二 EMF文件 二 文件解析 一 SPL格式 二 打开SPL文件 三 解析SPL文件 三 编程思路 一 记录EMF文件的位置和大小 二 找
  • JS对象的深复制

    JS实现对象的深复制 function cloneObject source target var list number string boolean undefined null function if target undefined
  • 区块链的安全性与去中心化特点:深入探讨区块链技术的安全性和去中心化特点

    摘要 本文将深入探讨区块链技术的两个核心特点 安全性和去中心化 区块链作为一种分布式账本技术 通过其独特的安全性和去中心化特点 在许多领域引起了广泛关注 我们将分析区块链的安全性原理和其与去中心化的关系 以及区块链技术在保护数据安全和提供信
  • 【Web常规漏洞】SSRF服务端请求伪造漏洞

    文章目录 参考 概念 产生原因 可能存在漏洞的代码 漏洞分类 潜在危害 漏洞利用 漏洞防御 漏洞绕过 概念 SSRF Server Side Request Forgery 服务器端请求伪造 是一种利用漏洞伪造服务器端发起请求 一般情况下
  • windows服务器被当矿机的问题处理实战-conhosts.exe

    windows服务器被当矿机的问题处理实战 conhosts exe 服务器最近比较卡 调开任务管理器查看 CPU占用偏高 发现进程 conhosts exe 占用CPU 75 通过pid查询 该进程通过syn sent向陌生IP 163
  • STM32G30C8T6hal库串口非固定长度

    1 由于从标准库转到hal库 还是特别不适应 串口测试遇到了一下问题 记录一下 2 hal库串口的配置不再赘述 hal库串口接收完毕可调用回调函数 接收的字节为固定长度才会回调 感觉非常麻烦 而且要重新开启接收中断 特别不适用于项目 想按照
  • 最新网络工程毕设选题题目推荐

    文章目录 0 简介 1 如何选题 2 最新网络工程选题 2 1 Java web SSM 系统 2 2 大数据方向 2 3 人工智能方向 2 4 其他方向 4 最后 0 简介 学长搜集分享最新的网络工程专业毕设毕设选题 难度适中 适合作为毕
  • python爬虫,多线程与生产者消费者模式

    使用队列完成生产者消费者模式 使用类创建多线程提高爬虫速度 https sc chinaz com tupian index html https sc chinaz com tupian index 2 html https sc chi
  • elasticsearch 安装教程

    一 jdk安装 es要求jdk版本在1 8以上 所以先安装jdk1 8 安装步骤 1 安装完Centos6 5的Base Server版会默认安装OpenJDK 首先需要删除OpenJDK 命令 rpm qa grep java 显示如下
  • 头条员工自爆:拿遍BAT和TMD的offer,面试过于NB!

    最近看到一位今日头条员工在脉脉发帖称 最近两次找工作 BAT TMD的offer几乎拿了个遍 但一般一家只能待两年 原因是面试的时候表现过于NB 导致下家对自己期望值过高 实际工作中面临的阻力很大的时候就会退缩 自己的能力项可能是面试 每次
  • Android 网络管理

    系统中对网络的判断和选在是在Connectivityervice这个服务中来处理的 在系统启动的时候会启动这个系统服务 系统启动完毕后 ConnectivityService在系统启动的时候就启动了 在android内部 用framewor
  • 如何学好C语言的数据结构与算法?

    C语言的数据结构与算法 难就难在链表 学会了链表 可能后面就一点都不难了 书籍推荐 数据结构与算法分析 C语言描述版 要深入学习的话可以选择这本书 因为针对链表的讲解是比较详细的 所以可以很快理解链表 跟着书上一点点实现基本操作 增删改查
  • Vue中的过滤器

    过滤器 定义 对要显示的数据进行特定格式化后再显示 适用于一些简单逻辑的处理 语法 1 注册过滤器 Vue filter name callback 全局 或 new Vue filters 局部 2 使用过滤器 xxx 过滤器名 或 v
  • 动态修改日志级别,太有用了!

    首发于公众号 BiggerBoy 背景 我们在系统中一般都会打印一些日志 并且在开发 测试 生产各个环境中的日志级别可能不一样 在开发过程中为了方便调试打印了很多debug日志 但是生产环境为了性能 为了节约存储资源 我们会将日志级别设置为
  • linux shell进行数值计算

    出于项目需要 需要用脚本执行计算 最简单的方法1 这里写算式 可以写变量 Desktop cat test sh a 102 c a 123 echo a a echo a 123 c Desktop test sh a 102 a 123
  • 【软件测试】用例篇

    一 什么是测试用例 测试用例 向被测试系统发起的一组集合 这组集合包含测试数据 测试步骤 测试平台 预期结果 二 为什么在测试前要设计测试用例 三 基于需求设计测试用例 3 1测试是我们测试人员进行测试的依据 3 2测试人员首先要分析需求
  • A-LOAM总结-(前端+后端)算法流程分析

    文章目录 scanRegistration cpp 雷达信息预处理进程 laserOdometry cpp laserMapping cpp A LOAM算法流程 主要运行以下3个cpp文件 流程框图在文末 scanRegistration
  • (C语言)输出数组的最大值及其对应下标的最小值

    本题源自pintia cn 题目要求 代码 测试结果图 PTA测试结果 题目要求 本题要求编写程序 找出给定的n个数中的最大值及其对应的最小下标 下标从0开始 输入格式 输入在第一行中给出一个正整数n 1
  • 为什么学完Python后的薪资这么高?

    人工智能和大数据概念的兴起 带动了Python的快速增长 Python语言逻辑简洁 入门简单 生态丰富 几乎成为几个新兴领域的不二选择 而除了这两个领域 Python还有更多的适用领域 爬虫 web 自动化运维等领域都非常适合Python发
  • 详细的Python Flask的操作

    本篇文章是Python Flask 建站框架入门课程 编程实战微课 w3cschool微课的学习笔记 根据课程整理而来 本人使用版本如下 Python 3 10 0 Flask 2 2 2 简介 Flask是一个轻量级的可定制的web框架