作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白
系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发
如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步
如果感觉博主的文章还不错的话,请三连支持一下博主哦
博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
python入门到实战专栏:从入门到实战
Python爬虫开发专栏:从入门到实战
Python办公自动化专栏:从入门到实战
Python数据分析专栏:从入门到实战
Python前后端开发专栏:从入门到实战
目录
Flask入门
Flask的安装
运行方式
Debug模式与配置参数加载
URL与函数的映射(动态路由)
URL路径参数
自定义转换器
查询参数的获取
请求体参数
上传文件
其它参数
Flask的介绍
Flask 是一款发布于2010年非常流行的 Python Web 框架。
特点
1 、微框架、简洁,给开发者提供了很大的扩展性。
2 、Flask和相应的插件写得很好,用起来很爽。
3、开发效率非常高,比如使用 SQLAlchemy 的 ORM 操作数据库可以节省开发者大量书写 sql 的时间。
Flask 的灵活度非常之高,他不会帮你做太多的决策,很多都可以按照自己的意愿进行更改。
比如:
使用 Flask 开发数据库的时候,具体是使用 SQLAlchemy 还是 MongoEngine,选择权完全掌握在你自己的手中。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展 Flask-Mail ,用户认证 Flask-Login ,数据库 Flask-SQLAlchemy ),都需要用第三方的扩展来实现。
Flask 没有默认使用的数据库,你可以选择 MySQL ,也可以用 NoSQL 。
其 WSGI 工具箱采用 Werkzeug (路由模块),模板引擎则使用 Jinja2 。这两个也是 Flask 框架的核心。
扩展列表:http://flask.pocoo.org/extensions/
Flask-SQLalchemy | 操作数据库 |
Flask-script | 插入脚本 |
Flask-migrate | 管理迁移数据库 |
Flask-Session | Session存储方式指定 |
Flask-WTF | 表单 |
Flask-Mail | 邮件 |
Flask-Bable | 提供国际化和本地化支持,翻译 |
Flask-Login | 认证用户状态 |
Flask-OpenID | 认证 |
Flask-RESTful | 开发REST API的工具 |
Flask-Bootstrap | 集成前端Twitter Bootstrap框架 |
Flask-Moment | 本地化日期和时间 |
Flask-Admin | 简单而可扩展的管理接口的框架 |
文档地址
1、 中文文档(http://docs.jinkan.org/docs/flask/)
2、 英文文档(http://flask.pocoo.org/docs/1.0/)
pip install flask
第一个Flask程序
#从flask包中导入Flask类
from flask import Flask
#创建一个Flask对象
app = Flask(__name__)
#@app.route:是一个装饰器
#@app.route('/')就是将url中 / 映射到hello_world设个视图函数上面
#以后你访问我这个网站的 / 目录的时候 会执行hello_world这个函数,然后将这个函数的返回值返回给浏览器
@app.route('/')
def hello_world():
return '艾派徳'
#启动这个WEB服务
if __name__ == '__main__':
#默认为5000端口
app.run() #app.run(port=8000)
启动运行
python helloworld.py
通过对象运行
运行程序时,可以指定运行的主机IP地址,端口
app.run(host="0.0.0.0", port=5000) # 127.0.0.1
参数解释
host
主机IP地址,可以不传
默认localhost
port
端口号,可以不传
默认5000
通过Python运行方式运行
app = Flask(__name__)
@app.route("/")
def index():
return "hello world"
if __name__ == '__main__':
app.run()
提示
如果想在同一个局域网下的其他电脑访问自己电脑上的Flask网站,需要设置 host='0.0.0.0' 才能访问得到
通过Flask自带命令运行
app = Flask(__name__)
@app.route("/")
def index():
return "hello world"
# 程序中不用再写app.run()
$ export FLASK_APP=helloworld
$ flask run
* Running on http://127.0.0.1:5000/
举例
flask run -h 0.0.0.0 -p 8000
注意
命令行下,可以使用使用简写
可以通过 flask run --help 获取帮助
-h, --host TEXT The interfaceto bind to.
-p, --port INTEGER The port tobind to.
--reload / --no-reload Enable or disable the reloader. By default
the reloader is active if debug is enabled.
--debugger / --no-debugger Enable or disable the debugger. By default
--help Show this message and exit.
在代码中制作一个错误
@app.route('/')
def hello_world():
a = 1
b = 0
c = a/b
return 'Hello World!'
if __name__ == '__main__':
app.run()
启动并访问
控制台倒是给出了错误提示信息,但是我们希望在浏览器也能有相应的提示信息
开启Debug模式
运行时传递参数
app.run(debug = True)
通过 app.deubg 参数设置
app.debug = True
app.run()
通过修改配置参数 config
app.config.update(DEBUG=True)
# app.config['DEBUG'] = True
app.run()
通过mapping加载
app.config.from_mapping({'DEBUG':True})
app.run()
通过配置对象设置 config
class Config:
DEBUG = True
app.config.from_object(config)
app.run()
通过配置文件设置 config
config.py
DEBUG = True
config.json
{"DEBUG":"True"}
app.py
app.config.from_pyfile('config.py')
app.config.from_json('config.json')
通过环境变量
DEBUG = True
app.config.from_envvar('DEBUG')
比如,有一个请求访问的接口地址为 /users/11001 ,其中 11001 实际上为具体的请求参数,表明请求 11001 号用户的信息。
此时如何从url中提取出 11001 的数据?
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user{}'.format(user_id)
其中 ,尖括号是固定写法,语法为 , variable 默认的数据类型是字符串。
如果需要指定类型,则要写成 converter:variable ,其中 converter 就是类型名称,可以有以下几种:
1、 string:如果没有指定具体的数据类型,那么默认就是使用 string 数据类型。
2、 int:数据类型只能传递 int 类型。
3、 float:数据类型只能传递 float 类型。
4、path:数据类型和 string 有点类似,都是可以接收任意的字符串,但是 path 可以接收路径,也就 是说可以包含斜杠。
5、 uuid:数据类型只能接收符合 uuid 的字符串。 uuid 是一个全宇宙都唯一的字符串,一般可以用来作为表的主键。
6 、any:数据类型可以在一个 url 中指定多个路径。例如:
将上面的例子以整型匹配数据,可以如下使用:
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return f'正在获取 ID {user_id} 的用户信息'
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return f'hello user {user_id}'
注意
若是数据与设置的类型不能匹配,则会返回 Not Found
问题
为什么路径参数可以直接识别数据类型?
提示
从 werkzeug.routing 导入 BaseConverter 类了解底层
int 路径参数底层调用 IntegerConverter 类来作格式判断
float 路径参数底层调用 FloatConverter 类来作格式判断
string 路径参数底层调用 StringConverter 类来作格式判断
如果遇到需要匹配提取 /sms_codes/1688888888 中的手机号数据,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)
to_python
在转换器类中,实现 to_python(self,value) 方法,这个方法的返回值,将会传递到 view函数中作为参数
to_url
在转换器类中,实现 to_url(self,values) 方法,这个方法的返回值,将会在调用url_for函数的时候生成符合要求的URL形式。
#需求2:查询多个模块的数据
#传统的思路实现
@app.route('/news_list//')
def news_list(modules):
#modules是路径参数
print(modules)
#http://127.0.0.1:5000/news_list/hots+enter/
#需要对modules进行拆分
lm = modules.split('+')
print(lm)
print(lm[0])
print(lm[1])
#拆分后需要去数据库 select * from news where nmodule= 'hots' ornmoudle= 'enter'
return f'你要查询的模块是:{lm}'
class LiConverter(BaseConverter):
# 1.在转换器类中,实现to_python(self,value)方法,这个方法的返回值,将会传递到 view函数中作为参数。
def to_python(self, value):
return value.split('+') #可以对value进行加工后再返回
# 2.在转换器类中,实现to_url(self,values)方法,这个方法的返回值,将会在调用url_for函数的时候生成符合要求的URL形式。
def to_url(self, value):
# return "hello"
#['hots','enter']---->hots+enter
return "+".join(value)
app.url_map.converters['li']=LiConverter
http://127.0.0.1:5000/test/?wd=python&ie=ok
from flask import Flask,request
app = Flask(__name__)
@app.route('/')
def index():
wd = request.args.get('wd')
ie = request.values.get('ie')
return f"Hello! {wd} == {ie}"
if __name__ == '__main__':
app.run(debug=True)
使用总结
如果你的这个页面的想要做 SEO 优化,就是被搜索引擎搜索到, 那么推荐使用第一种形式(path的形式)。 如果不在乎搜索引擎优化,那么就可以使用第二种(查询字符串的形式)。
from flask import Flask,request
app = Flask(__name__)
@app.route('/',methods=['POST'])
def index():
uname = request.form.get('uname')
pwd = request.values.get('pwd')
age = request.form.get('age')
return f"Hello! {uname} == {pwd} == {age}"
if __name__ == '__main__':
app.run(debug=True)
客户端上传图片到服务器,并保存到服务器中
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 '上传成功!'
如果想要获取其他地方传递的参数,可以通过Flask提供的request 对象来读取。 不同位置的参数都存放在request的不同属性中
属性 | 说明 | 类型 |
values | 记录请求的数据,并转换为字符串 | * |
form | 记录请求中的表单数据 | MultiDict |
args | 记录请求中的查询参数 | MultiDict |
cookies | 记录请求中的cookie信息 | Dict |
headers | 记录请求中的报文头 | EnvironHeaders |
method | 记录请求使用的HTTP方法 | GET/POST |
url | 记录请求的URL地址 | string |
files | 记录请求上传的文件 | * |
from flask import Flask,request
app = Flask(__name__)
@app.route('/args')
def args():
cookies = request.cookies.get('uid')
headers = request.headers.get('ContentType')
url = request.url
method = request.method
return f'上传成功!! {cookies} == {headers} =={url} == {method}'
if __name__ =='__main__':
app.run(debug=True)