Flask 速查手册

FLASK框架

安装

# Centos 8
pip3 install flask sqlalchemy flask_sqlalchemy pymysql mod_wsgi

Apache + mod_wsgi

# 编译安装
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(一键多值字典)。
argsMultiDict,要操作 URL (如 ?key=value )中提交的参数可以使用 args 属性: searchword = request.args.get('key', '')
valuesCombinedMultiDict,内容是form和args。 可以使用values替代form和args。
cookies请求的cookies,类型是dict。
stream在可知的mimetype下,如果进来的表单数据无法解码,会没有任何改动的保存到这个 stream 以供使用。很多时候,当请求的数据转换为string时,使用data是最好的方式。这个stream只返回数据一次。
headers请求头,字典类型。
data包含了请求的数据,并转换为字符串,除非是一个Flask无法处理的mimetype。
filesMultiDict,带有通过POST或PUT请求上传的文件。
environWSGI隐含的环境配置。
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蓝图名字。
endpointendpoint匹配请求,这个与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
        

操作

SQLAlchemySession对象管理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