Flask 速查手册
FLASK框架
安装
# Centos 8
pip3 install flask sqlalchemy flask_sqlalchemy pymysql mod_wsgi
Apache + mod_wsgi
-
指导手册 : https://modwsgi.readthedocs.io/en/develop/user-guides/quick-installation-guide.html
-
mod_wsgi : https://github.com/GrahamDumpleton/mod_wsgi/releases
# 编译安装
tar xvfz mod_wsgi-X.Y.tar.gz
./configure --with-apxs=/usr/bin/apxs--with-python=/usr/bin/python3
make && make install
# 配置文件语法
WSGIScriptAlias / /var/www/html/app.wsgi
# /etc/httpd/conf.modules.d/10-wsgi-python3.conf
<IfModule !wsgi_module>
LoadModule wsgi_module "/usr/local/lib64/python3.9/site-packages/mod_wsgi/server/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so"
</IfModule>
蓝图
-
一个项目可以具有多个Blueprint
-
可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/sample”或者子域名
-
在一个应用中,一个模块可以注册多次
-
Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现。
在一个应用初始化时,就应该要注册需要使用的Blueprint。
# 包含的包
from flask import Blueprint
# 蓝图注册
from users import users
app.register_blueprint(bp1,
url_prefix='/prefix',
static_folder='static'
static_url_path='/lib',
template_folder='templates_users') # 系统templates的优先级仍旧较高
#创建蓝图
bp1=Blueprint('bp1',__name__)
路由
@app.route('/hello')
def hello_world():
return 'hello world'
### OR
app.add_url_rule('/', '函数名字', hello_world)
app.add_url_rule('/index/',endpoint='index',view_func=index)
app.add_url_rule('/index/',view_func=index)
URL变量
@app.route('/hello/<name>')
def hello_name(name):
return 'Hello %s!' % name
@app.route('/blog/<int:postID>') # int,float,path
def show_blog(postID):
return 'Blog Number %d' % postID
t
@app.route('/rev/<float:revNo>')
def revision(revNo):
return 'Revision Number %f' % revNo
规范URL
@app.route('/flask') # 不规范!
def hello_flask():
return 'Hello Flask'
@app.route('/python/') # 规范
def hello_python():
return 'Hello Python'
路由方法
from flask import make_response,render_template,request,jsonify
@app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
user = request.form['nm']
return redirect(url_for('success',name = user))
else:
user = request.args.get('nm')
return redirect(url_for('success',name = user))
模板
在项目下创建 templates 文件夹,用于存放所有模板文件。
from flask import make_response,render_template,jsonify
@app.route('/')
def index():
return render_template('hello.html')
# OR
return render_template('hello.html',
my_str=my_str,
my_int=my_int,
my_array=my_array,
my_dict=my_dict
)
# 在初始化的时候可以指定模板的文件位置
app = Flask(__name__,template_folder='../xxxx');
静态文件
可以直接访问的文件
# 在初始化的时候可以指定静态文件的文件位置
app = Flask(__name__,static_folder="../xxxx");
<html>
<head>
<!-- 在html文件中获取静态目录的地址 -->
<script type = "text/javascript"
src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
</head>
<body>
<input type = "button" onclick = "sayHello()" value = "Say Hello" />
</body>
</html>
Request
Request对象的重要属性如下所列:
- Form - 它是一个字典对象,包含表单参数及其值的键和值对。
- args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
- Cookies - 保存Cookie名称和值的字典对象。
- files - 与上传文件有关的数据。
- method - 当前请求方法。
- remote_addr - 客户端的IP
# 导入方式
from flask import make_response,render_template,request,jsonify
# 使用方法
ip = request.remote_addr
user = request.form['nm'] #post
user = request.args.get('nm') #get
属性名 | 解释 |
---|---|
form | 一个从POST和PUT请求解析的 MultiDict(一键多值字典)。 |
args | MultiDict,要操作 URL (如 ?key=value )中提交的参数可以使用 args 属性: searchword = request.args.get('key', '') |
values | CombinedMultiDict,内容是form和args。 可以使用values替代form和args。 |
cookies | 请求的cookies,类型是dict。 |
stream | 在可知的mimetype下,如果进来的表单数据无法解码,会没有任何改动的保存到这个 stream 以供使用。很多时候,当请求的数据转换为string时,使用data是最好的方式。这个stream只返回数据一次。 |
headers | 请求头,字典类型。 |
data | 包含了请求的数据,并转换为字符串,除非是一个Flask无法处理的mimetype。 |
files | MultiDict,带有通过POST或PUT请求上传的文件。 |
environ | WSGI隐含的环境配置。 |
method | 请求方法,比如POST、GET。 |
path | 获取请求文件路径:/myapplication/page.html |
base_url | 获取域名与请求文件路径:http://www.baidu.com/myapplication/page.html |
url | 获取全部url:http://www.baidu.com/myapplication/page.html?id=1&edit=edit |
url_root | 获取域名:http://www.baidu.com/ |
is_xhr | 如果请求是一个来自JavaScript XMLHttpRequest的触发,则返回True,这个只工作在支持X-Requested-With头的库并且设置了XMLHttpRequest。 |
blueprint | 蓝图名字。 |
endpoint | endpoint匹配请求,这个与view_args相结合,可是用于重构相同或修改URL。当匹配的时候发生异常,会返回None。 |
json | 如果mimetype是application/json,这个参数将会解析JSON数据,如果不是则返回None。 可以使用这个替代get_json()方法。 |
max_content_length | 只读,返回MAX_CONTENT_LENGTH的配置键。 |
module | 如果请求是发送到一个实际的模块,则该参数返回当前模块的名称。这是弃用的功能,使用blueprints替代。 |
routing_exception = None | 如果匹配URL失败,这个异常将会/已经抛出作为请求处理的一部分。这通常用于NotFound异常或类似的情况。 |
url_rule = None | 内部规则匹配请求的URL。这可用于在URL之前/之后检查方法是否允许(request.url_rule.methods) 等等。 默认情况下,在处理请求函数中写下 print('request.url_rule.methods', request.url_rule.methods) 会打印: request.url_rule.methods {‘GET’, ‘OPTIONS’,‘HEAD’} |
view_args = None | 一个匹配请求的view参数的字典,当匹配的时候发生异常,会返回None。 |
其他方法 | get_json(force=False, silent=False, cache=True) on_json_loading_failed(e) |
重定向
# 函数原型
Flask.redirect(location, statuscode, response)
- location : 是应该重定向响应的URL。
- statuscode :发送到浏览器标头,默认为302。
- HTTP_300_MULTIPLE_CHOICES
- HTTP_301_MOVED_PERMANENTLY
- HTTP_302_FOUND
- HTTP_303_SEE_OTHER
- HTTP_304_NOT_MODIFIED
- HTTP_305_USE_PROXY
- HTTP_306_RESERVED
- HTTP_307_TEMPORARY_REDIRECT
- response :用于实例化响应。
# 例子
@app.route('/login',methods = ['POST', 'GET'])
def login():
return redirect(url_for('success'))
带错误码的abort函数
Flask.abort(code)
- code参数可以是以下之一
- 400 - 用于错误请求
- 401 - 用于未身份验证的
- 403 - Forbidden
- 404 - 未找到
- 406 - 表示不接受
- 415 - 用于不支持的媒体类型
- 429 - 请求过多
Cookies
操作 | 代码 |
---|---|
设置 | resp = make_response("success") resp.set_cookie("name", "value", max_age=3600) |
删除 | resp = make_response("delete") resp.delete_cookie("name") |
获取 | cookie_1 = request.cookies.get("name") |
# 1. 最后不要忘记
return resp;
# 2. 删除cookie只是让其过期。
# 3. 设置Cookie时不指定过期时间就是浏览器关闭后过期
Session
为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的SECRET_KEY。
# 修改session的信息
app.config.update(
SESSION_COOKIE_NAME = 'session',
SECRET_KEY = '此处应该是随机的KEY')
# OR
app.config['SECRET_KEY'] = '此处应该是随机的KEY'
# OR
app.secret_key = '此处应该是随机的KEY'
# 修改Session过期时间(默认是浏览器关闭过期)
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(hours=10) #10小时过期
# OR
session.permanent = True # 默认False,若设为True,则会存储31天
## 生成SECRET_KEY 小技巧
import os
os.urandom(24)
操作 | 代码 |
---|---|
设置 | session[‘name’] = ’value’ |
删除 | session.pop('name', None) |
获取 | session.get('name') ; # 不存在返回None,第二个参数是为空返回的的参数 |
清空 | session.clear() |
# redis 配置示例
app.config.update(
SESSION_TYPE = 'redis',
SESSION_REDIS = Redis(
host = "127.0.0.1",
port = 6379
),
SESSION_COOKIE_NAME = 'session',
)
Sqlalchemy 数据库操作
配置文件
db1 = "mysql+pymysql://root:密码@127.0.0.1:3306/数据库名字?charset=utf8"
db2 = "mysql+pymysql://root:密码@127.0.0.1:3306/数据库名字?charset=utf8"
app.config.update(
SQLALCHEMY_BINDS = {
'数据库A': db1,
'数据库B' : db2
},
SQLALCHEMY_COMMIT_ON_TEARDOWN = True, # 请求结束后自动提交数据库 (获取id手动commit)
SQLALCHEMY_TRACK_MODIFICATIONS = True
)
表定义(ORM)
db = SQLAlchemy(app) # 别忘了这个!!
class UceUser(db.Model):
__bind_key__ = '数据库名字'
__tablename__ = '表名字'
uid = Column(Integer, primary_key=True)
username = Column(String(32), unique=True,nullable=False)
phone = Column(BigInteger,unique=True,nullable=False)
email = Column(String(50), unique=True,nullable=False)
level = Column(Integer, nullable=False)
password = Column(String(64), nullable=False)
def __init__(self,u,un,p,e,l,pw):
self.uid = u
self.username = un
self.phone = p
self.email = e
self.level = l
self.password = pw
操作
SQLAlchemy的Session对象管理ORM**对象的所有持久性操作。
以下session方法执行CRUD操作:
- **db.session.add (模型对象) - 将记录插入到映射表中
- db.session.delete (模型对象) - 从表中删除记录
- model.query.all() - 从表中检索所有记录(对应于SELECT查询)。
创建
db.create_all()
查询
表名
# 表内精确查询
表名.query.filter(表名.列名 == 'value').all() # 全局查询
# ... .first()
# ... .all()
from sqlalchemy import or_,and_,in_,is_,isnot
# 高级用法
query.filter(User.name != 'ed')
query.filter(User.name.like('%ed%'))
query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%ed%'))))
query.filter(~User.name.in_(['ed','wendy','jack']))
query.filter(User.name.is_(None))
query.filter(User.name.isnot(None))
query.filter(and_(User.name=='ed',User.fullname=='Ed Jones')) # and
query.filter(User.name=='ed',User.fullname=='Ed Jones') # and
query.filter(User.name=='ed').filter(User.fullname=='Ed Jones') # and
query.filter(or_(User.name=='ed',User.name=='wendy')) # or
#limit
query.filter(User.name != 'ed').limit(10)
# 前缀部分
表名.query.filter
# OR
session.query(表名).filter
# OR
db.session.add(表实例)
##### 修改
user = User.query.get(20)
user.name ='小名'
db.session.commit()
自增ID
result = db.session.execute(sql)
session.commit()
return result.lastrowid