flask项目创建
蓝图blueprint
帮助我们对flask程序进行目录结构的划分
flask mtv
django mvc
- before_request
from flask import Flask def create_app(): app = Flask(__name__) @app.before_request def f1(): print('f1') from .views.account import account from .views.user import user app.register_blueprint(account) app.register_blueprint(user) return app
from flask import Blueprint,url_for # 创建了一个蓝图对象 account = Blueprint('account',__name__) # 两个必要参数'account'蓝图名字;'__name__'蓝图所在的模块或者包,一般为'__name__'变量 # account = Blueprint('account', __name__, url_prefix='/xx') #为url添加前缀,url为/xx/account才能访问account()函数 @account.before_request def xx(): print('xx')
- url_for
from flask import Blueprint,url_for # 创建了一个蓝图对象 account = Blueprint('account',__name__) @account.before_request def xx(): print('xx') @account.route('/login') def login(): url = url_for('account.register') print(url) return 'Login' @account.route('/register') def register(): return 'register'
目录结构
创建完成后显示一个crm文件
需要手动创建下图目录结构
例子
创建__init__.py文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from flask import Flask def create_app(): app = Flask(__name__) @app.before_request def f1(): print('f1') from .views.account import account from .views.user import user app.register_blueprint(account) app.register_blueprint(user) return app
创建manage.py运行文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from crm import create_app app = create_app() if __name__ == '__main__': app.run(port=8000)
创建views用写视图
在视图创建两个文件
account.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from flask import Blueprint,url_for # 创建了一个蓝图对象 account = Blueprint('account',__name__) @account.before_request def xx(): print('xx') @account.route('/login') def login(): url = url_for('account.register') print(url) return 'Login' @account.route('/register') def register(): return 'register'
user.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from flask import Blueprint user =Blueprint('user',__name__) @user.route('/user/list') def user_list(): return 'user list' @user.route('/user/add') def user_add(): return 'user add'
数据库连接池
原生sql 单例模式
pip3 install DBUtils
快速使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time import threading import pymysql from DBUtils.PooledDB import PooledDB # 创建数据库连接池 POOL = PooledDB( creator=pymysql, maxconnections=20, mincached=2, host='127.0.0.1', port=3306, user='root', password='123', database='pooldb', charset='utf8' ) # 去数据库连接池获取一个连接 conn = POOL.connection() cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('select * from tb1') result = cursor.fetchall() # 将此连接放还给连接池 conn.close()
flask应用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pymysql from DBUtils.PooledDB import PooledDB class SQLHelper(object): def __init__(self): # 创建数据库连接池 self.pool = PooledDB( creator=pymysql, maxconnections=5, mincached=2, blocking=True, host='127.0.0.1', port=3306, user='root', password='123', database='s23day02', charset='utf8' ) def connect(self): conn = self.pool.connection() cursor = conn.cursor() return conn,cursor def disconnect(self,conn,cursor): cursor.close() conn.close() def fetchone(self,sql,params=None): """ 获取单条 :param sql: :param params: :return: """ if not params: params = [] conn,cursor = self.connect() cursor.execute(sql, params) result = cursor.fetchone() self.disconnect(conn,cursor) return result def fetchall(self,sql,params=None): """ 获取所有 :param sql: :param params: :return: """ import pymysql if not params: params = [] conn, cursor = self.connect() cursor.execute(sql,params) result = cursor.fetchall() self.disconnect(conn, cursor) return result def commit(self,sql,params): """ 增删改 :param sql: :param params: :return: """ import pymysql if not params: params = [] conn, cursor = self.connect() cursor.execute(sql, params) conn.commit() self.disconnect(conn, cursor) db = SQLHelper()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from flask import Blueprint,url_for,request,render_template,session,redirect from ..utils.sqlhelper import db # 创建了一个蓝图对象 account = Blueprint('account',__name__) @account.route('/login',methods=['GET','POST']) def login(): if request.method == 'GET': return render_template('login.html') user = request.form.get('user') pwd = request.form.get('pwd') # 根据用户名和密码去数据库进行校验 # 连接/SQL语句/关闭 result = db.fetchone('select * from user where username=%s and password=%s',[user,pwd]) if result: # 在session中存储一个值 session['user_info'] = user return redirect(url_for('user.user_list')) return render_template('login.html',error="用户名或密码错误")
DBUtils连接池的应用及基于单例模式企业SQLHelper的封装
对用户提交的数据进行格式校验. (django form )
pip3 install wtforms
知识点:
-
-
定义字段(label/validate/default/choices...)
-
钩子函数
-
重写init在init中去数据库中获取数据并赋值 self.hobby.choices = ...
-
-
使用类
-
form = Form(),默认只展示标签.
-
form = Form(data={'name':'xx'}) 显示标签+默认值 (用于编辑)
-
form = Form(formdata=request.form) 用于接收用户提交的数据,
-
if form.validate(): form.data else: form.errors
创建setting.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Base(object): CHARSET = 'utf8' PORT = 3306 class Prod(Base): HOST = '10.11.11.11' USER = 'test' PASSWORD = '123' DATABASE = 'dbtest' class Test(Base): HOST = '13.16.55.89' USER = 'test' PASSWORD = '123' DATABASE = 'dbtest' class Dev(Base): HOST = '127.0.0.1' USER = 'root' PASSWORD = '123' DATABASE = 's23day02'
在__init__下
def create_app(): app = Flask(__name__) app.secret_key = '93jls98029ulsdu092ujlkd' app.config.from_object('settings.Dev')
...
return app
调用时
from flask import current_app current_app.config
注意:程序加载的顺序
class Foo(object): pass obj = Foo() obj.x1 = 123 # object.__setattr__(obj,'x1',123) print(obj.x1) # object.__getattr__(obj,'x1')
class Local(object): def __init__(self): # self.storage = {} object.__setattr__(self,'storage',{}) def __setattr__(self, key, value): self.storage[key] = value def __getattr__(self, item): return self.storage[item] obj = Local() obj.x1 = 123 print(obj.x1)
import threading """ { 1231:{x1:0}, 1432:{x1:1}, ... 5321:{x1:9} } """ class Local(object): def __init__(self): # self.storage = {} object.__setattr__(self,'storage',{}) def __setattr__(self, key, value): # self.storage[key] = value ident = threading.get_ident() # 1233 if ident in self.storage: self.storage[ident][key] = value else: self.storage[ident] = {key:value} def __getattr__(self, item): ident = threading.get_ident() return self.storage[ident][item] obj = Local() def task(arg): obj.x1 = arg print(obj.x1) for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
flask上下文管理机制?
当用户请求到来之后,flask内部会创建两个对象: ctx = ReqeustContext(),内部封装request/sesion app_ctx = AppContext(),内部封装app/g 然后会将此对象通过各自的LocalStack对象: _request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack() 将各自的对象添加到local中. Local是一个特殊结构,他可以为每个线程(协程)维护一个空间进行存取数据. LocalStack的作用是将Local中维护成一个栈. 内部更细节的结构我也研究过: storage = { 1212:{stack:[ctx,]} } storage = { 1212:{stack:[app_ctx,]} } 视图函数如果想要获取:request/session/app/g,只需要导入即可,导入的本质是去各自storage中获取各自的对象,并调用封装其内部:request/session/app/g. (获取栈顶的数据top) 请求处理完毕,将各自storage中存储的数据进行销毁.
flask离线脚本
- 离线脚本
-
web运行时: 启动网站,等待用户通过浏览器发来请求. 离线脚本: 写一个py文件临时做一些事情.
-
面向对象的特殊方法
class Foo: def __enter__(...): pass def __exit__(...): pass obj = Foo() with obj: pass
flask的配置文件
app = Flask(__name__) # 去对象中读取配置文件 app.config.from_object('xx.xxx') # 5 # 获取配置文件 print(app.config) # 15 @app.route('/index') def index(): return "123" app.run()
app对象中包含了配置文件.
当用户请求到来时候,flask会将ctx/app_ctx对象放到各自的local中,以后再去获取.
离线脚本
把文件的内容导到数据库
把某个数据库表中的数据导出到另外一个数据库等.
import pymysql from flask import current_app from crm import create_app # 方式一:获取配置文件 # app = create_app() # print(app.config) # 方式二:获取配置文件(居多) app1 = create_app() # 将此对象放到Local中 with app1.app_context(): print(current_app.config) # top app2 = create_app() with app2.app_context(): print(current_app.config) # top print(current_app.config) # top
项目启动,即:运行之后发生了什么?
from flask import Flask # 1.实例化Flask对象,执行Flask类的 __init__方法. app = Flask(__name__) @app.route('/login') def login(): return "login" @app.route('/index') def index(): return "index" if __name__ == '__main__': app.run()
处理用户请求阶段
相当于是flask中一次请求周期中可用的一个 "全局变量",本质上是放在local对象的app_ctx中. 应用场景:权限校验.
-
-
threading.loal对象
obj = threading.local() obj.x1 = 123
- 蓝图
面试题:flask蓝图和django的app有什么区别? - 相同: 可以做业务的划分,django可以将不同业务放到不同app中,flask放在蓝图中. 使用时,都需要注册. 支持在URL中添加前缀. - 不同点: django的app比flask蓝图涵盖的东西更多. models url反向解析,flask中要加蓝图为前缀; django和app无关. before request的粒度. 目录结构实例
- wtforms
- flask相关问题
你都用过flask相关的哪些组件?
DBUtils
wtforms