FLASK目录
1.配置文件
2.路由系统
3.视图
4.请求相关
5.响应相关
6.模板渲染
7.闪现
8.session
9.中间件
10.蓝图
11.特殊的装饰器
12.WTForms
app.config.from_object('settings.Base') # 更改配置文件
常用的配置参数
static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录 static_url_path = None, # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用 template_folder = 'templates' # template模板目录, 默认当前项目中的 templates 目录
flask初始化配置
static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录 static_host = None, # 远程静态文件所用的Host地址,默认为空 static_url_path = None, # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用 # host_matching是否开启host主机位匹配,是要与static_host一起使用,如果配置了static_host, 则必须赋值为True # 这里要说明一下,@app.route("/",host="localhost:5000") 就必须要这样写 # host="localhost:5000" 如果主机头不是 localhost:5000 则无法通过当前的路由 host_matching = False, # 如果不是特别需要的话,慎用,否则所有的route 都需要host=""的参数 subdomain_matching = False, # 理论上来说是用来限制SERVER_NAME子域名的,但是目前还没有感觉出来区别在哪里 template_folder = 'templates' # template模板目录, 默认当前项目中的 templates 目录 instance_path = None, # 指向另一个Flask实例的路径 instance_relative_config = False # 是否加载另一个实例的配置 root_path = None # 主模块所在的目录的绝对路径,默认项目目录
@app.route('url地址',methods=['POST',"GET"],endpoint='别名',defaults={'nid':1},strict_slashes=True,redirect_to='/index')
endpoint:反向生成url,默认是函数名
endpoint= 相当于django中的name
url_for 相当于 reverse 不定义默认是函数名
defaults:默认参数
strict_slashes:True 严格要求访问的方式,
redirect_to='url':301重定向:永久重定向
1.FBV 函数就是FBV 2.CBV
from flask import views class User(views.MethodView): methods = ['GET'] decorators = ['装饰器'] def dispatch_request(self, *args, **kwargs): pass def get(self): self.dispatch_request() pass def post(self): pass app.add_url_rule('/user/',User.as_view('endpoint')) 自定义正则 from werkzeug.routing import BaseConverter 1.定义一个类 ,BaseConverter 2.添加到转换器 app.url_map.converters['reg'] = '类名' 3.使用自定义正则 to_python:匹配url的时候用 to_url:反向生成时候用
request参数(常用的) request.form # 存放form表单中的序列化数据 request.args # 存放url里面的序列化数据 request.values.to_dict() # 存放url和from中的所有数据 request.method # 存放请求方式 request.path 路由地址 request.url 所有的url:全部地址 request.host 主机位 127.0.0.1:5000 request.host_url 将主机位转换成url http://127.0.0.1:5000/ request.data 查看传过来所有解析不了的内容 request.json 查看前端传过来的json文件 request.headers 查看所有的请求头 file = request.files 前端传过来的文件 file.filename 返回文件名称 file.save() :保存文件
只有响应体 return '字符串' :返回一些字符串 return render_template() # 返回一个页面 return redirect() # 重定向 return jsonify # 返回JSON数据,返回标准的json格式字符串 content-type: application/json return send_file("2.mp3") # 打开文件并返回客户端 设置响应头 obj = make_response('字符串') obj.headers['响应头']='1111' obj.set_cookie():设置cookie return obj
{{ }} 引用变量 非逻辑代码时使用 {% %} 逻辑代码使用 -基本数据类型,可以执行python语法,如dict.get(),list[11] -传入函数 django,可以执行 flask,不自动执行 -全局定义 @app.template_global() @app.template_filter() -定义模板 {% extends %} 引入模板 {% include %} 引入一小部分 -宏定义 {% macro ccc(name,type='text',value='') %} <input type="{{ type }}" name={{ name }} value={{ value }}> <input type="button" value="提交"> {% endmacro %} {{ ccc('name') }} 运行 -安全 -前端 {{ll|safe}} -后端 Markup('字符串')
7.闪现
闪现,在session中存储一个数据,读取时通过pop将数据移出掉 flash('内容',category='ok')
参数:
第一个:内容
第二:分类
get_flashed_messages()获取flash
参数:
第一:with_categories=True True代表返回一个元祖
第二:category_filter='ok' 筛选条件
8.session
默认session的使用
当请求刚到来时,flask读取cookie中session对应的值,将该值解密并序列化成一个字典,并放入内存 当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户的cookie中 PERMANENT_SESSION_LIFETIME = timedelta(hours = 1) :小时:hours app.secret_key = 'xxxxxxx' :必须要加的,不加会报错
flask-sessiom的使用
from flask_session import Session
from flask import session
from redis import Redis
app.config['SESSION_TYPE']='redis'
app.config['SESSION_REDIS'] = Redis()
Session(app)
使用的时候继续使用flask的session,他会把你存储的内容放入redis
- app.__call__方法何时触发 用户发起请求时才触发 代码: class Middleware(): def __init__(self,old): self.old = old def __call__(self, *args, **kwargs): print('前') ret = self.old(*args, **kwargs) print('后') return ret app.wsgi_app = Middleware(app.wsgi_app)
目标:给开发者提供一个目录结构 from flask import Blueprint ac = Blueprint('ac',__name__,url_prefix='/ac') 注册蓝图: app.register_blueprint(ac) url_prefix:定义url前缀每次访问这个蓝图的时候,必须加/ac static_folder = 'xxx' :指定蓝图存储静态文件的位置 template_folder='xxx':指定模板存储的位置 自定义模板和静态文件,url前缀,
@app.template_global() 全局函数
@app.template_filter() 类似标签
@app.before_request 类似于process_request:没有参数 顺序:从上到下
@app.after_request 类似于process_response:必须有参数,并返回 顺序:从下到上:即使在第一个就返回,也会全部执行一遍
@app.before_first_request 只有第一次执行
@app.teardown_request 在有异常发生时触发
@app.errorhandler(404) 没找到页面走这个之下的函数,有一个参数
12.WTForms
创建数据库池
import time import pymysql import threading from DBUtils.PooledDB import PooledDB, SharedDBConnection POOL = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='123', database='pooldb', charset='utf8' )
使用数据库池
def func(): # 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常 # 否则 # 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。 # 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。 # 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。 # 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。 conn = POOL.connection() cursor = conn.cursor() cursor.execute('select * from tb1') result = cursor.fetchall() conn.close()
自制sqlhelper
class MySQLhelper(object): def __init__(self, host, port, dbuser, password, database): self.pool = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host=host, port=int(port), user=dbuser, password=password, database=database, charset='utf8' ) def create_conn_cursor(self): conn = self.pool.connection() cursor = conn.cursor(pymysql.cursors.DictCursor) return conn,cursor def fetch_all(self, sql, args): conn,cursor = self.create_conn_cursor() cursor.execute(sql,args) result = cursor.fetchall() cursor.close() conn.close() return result def insert_one(self,sql,args): conn,cursor = self.create_conn_cursor() res = cursor.execute(sql,args) conn.commit() print(res) conn.close() return res def update(self,sql,args): conn,cursor = self.create_conn_cursor() res = cursor.execute(sql,args) conn.commit() print(res) conn.close() return res sqlhelper = MySQLhelper("127.0.0.1", 3306, "root", "1233121234567", "dragon") # sqlhelper.fetch_all("select * from user where id=%s",(1)) # sqlhelper.insert_one("insert into user VALUES (%s,%s)",("jinwangba",4)) # sqlhelper.update("update user SET name=%s WHERE id=%s",("yinwangba",1))