第5章 章节五
01 内容概要
02 内容回顾
03 面向对象相关补充:metaclass(一)
04 面向对象相关补充:metaclass(二)
05 WTforms实例化流程分析(一)
06 WTforms实例化流程分析(二)
07 拓展:相关面试题
08 ORM框架概念
09 SQLAlchemy框架快速使用
10 SQLAlchemy框架组件使用
11 SQLAlchemy执行原生SQL
12 上述内容总结
13 SQLAlchemy创建表结构
14 SQLAlchemy实现基本增删改查(一)
15 SQLAlchemy实现基本增删改查(二)
16 SQLAlchemy小练习
17 SQLAlchemy常见操作
18 上述内容总结
19 homework
第6章 章节六
01 内容概要
02 内容回顾
03 WTforms组件验证流程
04 SQLAlchemy操作补充
05 homework
第7章 章节七
01 内容概要
02 内容回顾
03 Flask-script组件
04 FLask-SQLAlchemy组件应用(一)
05 Flask-SQLAlchemy组件应用(二)
06 Flask-SQLAlchemy组件应用(三)
07 Flask-SQLAlchemy组件应用总结
08 SQLAlchemy创建session的两种方式
09 Flask-Migrate组件
10 Flask自定义拓展
11 Flask多app应用
12 Flask信号blinker
13 Flask信号和before_request的区别
14 内容总结和作业
第5章 章节五
01 内容概要
1.1 面向对象相关;
- _mro__;
- metaclass;
1.2 WTforms;
1.3 SQLALchemy(Flask中的一个ORM框架);
1.4 SQLALchemy/flask-sqlalchemy;
1.5 flask其他;
- flask-script;
- flask-migrate;
- 多app应用;
- 离线脚本;
02 内容回顾
2.1 Flask和Django的区别;
1:重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择应用上花费大量时间;
2:自带ORM(Object-Relational Mapping 对象关联映射)和模板引擎,支持JinJa等非官方模板引擎,灵活度不高;
3:自带ORM使Django和关系型数据库耦合度过高,如果要使用非关系型数据库,需要使用第三方库;
4:自带数据库管理app;
5:成熟、稳定、开发效率高、相对于Flask,Django的整体封闭性比较好,适合做企业级网站的开发;
6:python web框架的先驱,第三方库丰富;
7:上手容易,开发文档详细、完善、资料丰富; 1:轻量级web框架,只有一个内核,默认依赖两个外部库:Jinja2 模板引擎和 Werkzeug WSGI 工具集,*,灵活,可扩展性强,开发者可以根据需求自己造*;
2:适用于做小型网站以及web服务的API,开发大型网站无压力,架构需自行设计;
3:与关系型数据库结合不弱于Django,而与非关系型数据库的结合远远优于Django;
2.2 Flask的上下文管理是如何实现的?
http://www.cnblogs.com/zhaopanpan/articles/9457343.html
问题一:flask和django的区别:
对于django来说,内部组件特别多,自身功能强大,有点大而全,而flask,内置组件很少,但是它的第三方组件很多,扩展性强,有点短小精悍,而它们之间也有相似之处,
因为它们两个框架都没有写sockte,都是基于wsgi协议做的,在此之外,flask框架中的上下文管理较为耀眼。
相同点:它们两个框架都没有写sockte,都是基于wsgi协议做的
请求相关数据传递的方式不同:django:通过传递request参数取值
flask:见问题二
组件不同:django组件多
flask组件少,第三方组件丰富 问题1.1: flask上下文管理:
简单来说,falsk上下文管理可以分为三个阶段:
1、请求进来时,将请求相关的数据放入上下问管理中
2、在视图函数中,要去上下文管理中取值
3、请求响应,要将上下文管理中的数据清除
详细点来说:
1、请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并通过LocalStack将requestcontext和appcontext放入Local类中
2、视图函数中,通过localproxy--->偏函数--->localstack--->local取值
3、请求相应时,先执行save.session()再各自执行pop(),将local中的数据清除
问题1.2 flask第三方组件
flask:
-flask-session 默认放入cookie,可以放入redis
-flask-redis
-flask-migrate
-flask-script
-blinker 信号
公共: DBUtils 数据库连接池
wtforms 表单验证+生成HTML标签
sqlalchemy
自定义:Auth 参考falsk-login 问题二:Flask中的session是什么时候创建,什么时候销毁的?
当请求进来时,会将requset和session封装为一个RequestContext对象,通过LocalStack将RequestContext放入到Local对象中,因为
请求第一次来session是空值,所以执行open_session,给session(uuid4())赋值,再通过视图函数处理,请求响应时执行save.session,将签名session写入cookie中,再讲Local中的数值pop掉。 问题三:flask中一共有几个LocalStack和Local对象
两个LocalStack,两个Local
request、session共同用一个LocalStack和Local
g、app共同用一个Localstack和Local 问题四: 为什么把请求放到RequestContext中:
因为request和session都是在视图中操作频繁的数据,也是用户请求需要用的数据,将request和session封装在RequestContext中top,pop一次就可以完成,而单独不封装在一起就会多次操作, ctx = RequestContext(request,session) 问题五:local作用
-保存 请求上下文对象和app上下文对象 -localstack的源码与threading.local(线程处理)作用相似,不同之处是Local是通过greenlet(协程)获取唯一标识,粒度更细
问题六:Localstack作用
2、将local对象中的数据维护成一个栈【ctx,ctx】(先进后出)
{
“协程或线程的唯一标识”: { stack:[ctx,ctx,ctx,] }
}
为什么维护成一个栈?
当是web应用时:不管是单线程还是多线程,栈中只有一个数据
- 服务端单线程:
{
111:{stack: [ctx, ]}
}
- 服务端多线程:
{
111:{stack: [ctx, ]}
112:{stack: [ctx, ]}
}
离线脚本:可以在栈中放入多个数据
with app01.app_context():
print(current_app)
with app02.app_context():
print(current_app)
print(current_app) 问题七:什么是g?
g 相当于一次请求的全局变量,当请求进来时将g和current_app封装为一个APPContext类,在通过LocalStack将Appcontext放入Local中,取值时通过偏函数,LocalStack、loca l中取值,响应时将local中的g数据删除:
问题八:怎么获取Session/g/current_app/request
通过 、偏函数(lookup_req_object)、Localstack、Local取值
问题九: 技术点:
- 反射 (LocalProxy())
- 面向对象,封装:RequestContext
- 线程(threading.local)
- 笔试:自己写一个类+列表 实现栈。(LocalStack)
问题十:python基本哪些内容比较重要:
1、反射
-CBV
-django配置文件
-wtforms中的Form()示例化中 将"_fields中的数据封装到From类中"
2、装饰器 (迭代器,生成器)
-flask:路由、装饰器 -认证
-csrf
3、面向对象
-继承、封装、多态(简单描述)
-双下划线:
__mro__ wtform中 FormMeta中继承类的优先级
__dict__
__new__ ,实例化但是没有给当前对象
wtforms,字段实例化时返回:不是StringField,而是UnboundField
rest frawork many=Turn 中的序列化
__call__
flask 请求的入口app.run()
字段生成标签时:字段.__str__ => 字段.__call__ => 插件.__call__
__iter__ 循环对象是,自定义__iter__ wtforms中BaseForm中循环所有字段时定义了__iter__
metaclass
- 作用:用于指定当前类使用哪个类来创建
- 场景:在类创建之前定制操作
示例:wtforms中,对字段进行排序。
2.3 Local的作用:
- 用于保存——请求上下文对象和app上下文对象;
- 做到“线程”间的数据隔离;
2.4 LocalStack作用?
- 将Local中保存的数据维护成一个栈(弹夹,后进先出);
2.5 Flask的内置组件;
- 配置
- 路由
- 视图
- 模板
- session
- 蓝图
- 闪现
- 装饰器
- 中间件
2.6 第三方组件;
- flask-session;私有,将原来保存在Cookies中的session数据保存在redis或者memcache中;
- DBUtils;公共,数据库连接池,维护数据库连接;
- WTforms;公共,用于做表单验证,生成html标签;
03 面向对象相关补充:metaclass(一)
3.1 面向对象相关-__mro__;
04 面向对象相关补充:metaclass(二)
4.1 metaclass的相关说明;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-21 16:31
# File : 3.metaclass.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
# 创建类的两种方式; # 方式一:
class Foo(object):
CITY = 'BJ' def func(self, x):
return x + 1 # 方式二: def func(self, x):
return x + 1 # Foo1 = type('Foo1', (object,), {'CITY': 'BJ', 'func': func}) # 另外一种形式:
Foo2 = type('Foo', (object,), {'CITY': 'BJ', 'func': lambda self, x: x + 1}) # 2、类由自定义type创建;
class Foo3(object, metaclass=type): # 当前类由type类创建;
# __metaclass__ = type# Python2的创建方式;
CITY = 'BJ' def func(self, x):
return x + 1 class MyType(type):
def __init__(self, *args, **kwargs):
print('创建类之前')
super(MyType, self).__init__(*args, **kwargs)
print('创建类之后') class Foo4(object, metaclass=MyType):
CITY = 'BJ' def func(self, x):
return x + 1 print(Foo4)
"""
1、类由type创建,metaclass可以指定当前类由哪一个类创建;
""" class MyType1(type):
def __init__(self, *args, **kwargs):
print('创建类之前')
super(MyType1, self).__init__(*args, **kwargs)
print('创建类之后') class Foo1(object, metaclass=MyType1):
CITY = 'BJ' def func(self, x):
return x + 1 class Bar(Foo):
pass """
小结:
1、默认类由type实例化创建;
2、某个类指定metaclass = MyType,那么当前类的所有派生类都由于MyType创建;
3、实例化对象:
-type.__init__
-type.__call__
-类名.__new__
-类名.__init__
"""
05 WTForms实例化流程分析(一)
5.1 WTForms的实例化流程;
# 源码流程
1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中; meta类读取到cls._wtforms_meta中
2. 执行构造方法 a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中。
即:
_fields = {
name: wtforms.fields.core.StringField(),
} PS:由于字段中的__new__方法,实例化时:name = simple.StringField(label='用户名'),创建的是UnboundField(cls, *args, **kwargs),当执行完bind之后,才变成执行 wtforms.fields.core.StringField() b. 循环_fields,为对象设置属性
for name, field in iteritems(self._fields):
# Set all the fields to attributes so that they obscure the class
# attributes with the same names.
setattr(self, name, field)
c. 执行process,为字段设置默认值:self.process(formdata, obj, data=data, **kwargs)
优先级:obj,data,formdata; 再循环执行每个字段的process方法,为每个字段设置值:
for name, field, in iteritems(self._fields):
if obj is not None and hasattr(obj, name):
field.process(formdata, getattr(obj, name))
elif name in kwargs:
field.process(formdata, kwargs[name])
else:
field.process(formdata) 执行每个字段的process方法,为字段的data和字段的raw_data赋值
def process(self, formdata, data=unset_value):
self.process_errors = []
if data is unset_value:
try:
data = self.default()
except TypeError:
data = self.default self.object_data = data try:
self.process_data(data)
except ValueError as e:
self.process_errors.append(e.args[0]) if formdata:
try:
if self.name in formdata:
self.raw_data = formdata.getlist(self.name)
else:
self.raw_data = []
self.process_formdata(self.raw_data)
except ValueError as e:
self.process_errors.append(e.args[0]) try:
for filter in self.filters:
self.data = filter(self.data)
except ValueError as e:
self.process_errors.append(e.args[0]) d. 页面上执行print(form.name) 时,打印标签 因为执行了:
字段的 __str__ 方法
字符的 __call__ 方法
self.meta.render_field(self, kwargs)
def render_field(self, field, render_kw):
other_kw = getattr(field, 'render_kw', None)
if other_kw is not None:
render_kw = dict(other_kw, **render_kw)
return field.widget(field, **render_kw)
执行字段的插件对象的 __call__ 方法,返回标签字符串
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms.fields import core
from wtforms.fields import html5
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets app = Flask(__name__, template_folder='templates')
app.debug = True class LoginForm(Form):
name = simple.StringField(
label='用户名',
validators=[
validators.DataRequired(message='用户名不能为空.'),
validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'} )
pwd = simple.PasswordField(
label='密码',
validators=[
validators.DataRequired(message='密码不能为空.'),
validators.Length(min=8, message='用户名长度必须大于%(min)d'),
validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",
message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符') ],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
) @app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
form = LoginForm()
return render_template('login.html', form=form)
else:
form = LoginForm(formdata=request.form)
if form.validate():
print('用户提交数据通过格式验证,提交的值为:', form.data)
else:
print(form.errors)
return render_template('login.html', form=form) if __name__ == '__main__':
app.run() app.py
06 WTforms实例化流程分析(二)
6.1 WTForms实例化流程分析;
a. 执行form的validate方法,获取钩子方法
def validate(self):
extra = {}
for name in self._fields:
inline = getattr(self.__class__, 'validate_%s' % name, None)
if inline is not None:
extra[name] = [inline] return super(Form, self).validate(extra)
b. 循环每一个字段,执行字段的 validate 方法进行校验(参数传递了钩子函数)
def validate(self, extra_validators=None):
self._errors = None
success = True
for name, field in iteritems(self._fields):
if extra_validators is not None and name in extra_validators:
extra = extra_validators[name]
else:
extra = tuple()
if not field.validate(self, extra):
success = False
return success
c. 每个字段进行验证时候
字段的pre_validate 【预留的扩展】
字段的_run_validation_chain,对正则和字段的钩子函数进行校验
字段的post_validate【预留的扩展】
07 拓展:相关面试题
7.1 Python基础部分哪些比较重要?
- 反射——CBV、Django的配置文件、WTForms;
- 装饰器——Flask路由、认证、CRSF
- 生成器、迭代器
- 面向对象——继承、封装和多态;特殊的功能:双下划线方法(__mro__、__dict__、__new__、__call__、__iter__)以及metaclass;
08 ORM框架概念
8.1 什么是ORM框架?
关系-对象-映射(Object-Object Relational Mapping);
当有了对应关系后,不再需要编写SQL语句,取而代之是操作:类、对象;
8.2 ORM和原生SQL的优缺点?
8.2.1 ORM;
- 快速开发
- 性能差
8.2.2 SQL;
- 性能好
- 开发速度慢
8.2.3 DB First(已经使用原生SQL开发,根据数据库的表生成类);
8.2.4 Code First(ORM是CodeFirst,根据类创建数据表);
- python3 manage.py inspect
8.2.5 ORM是如何实现的?内置解析器实现;通过对象和类转化成字符换;
09 SQLAlchemy框架快速使用
9.1 SQLAlchemy,是一个基于Python实现的ORM框架;
9.2 SQLAlchemy的快速使用;
ORM.py;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 09:54
# File : 1.ORM.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org ""
"""
SQLAlchemy插入数据操作;
"""
import models
#from sqlalchemy.ext.declarative import declarative_base
#from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session", max_overflow=5)
Session = sessionmaker(bind=engine)
session = Session() obj1 = models.Users(name="cuixiaozhao", extra="cxz")
obj2 = models.Users(name="cuixiaozhao", extra="cxz") session.add(obj1)
session.add(obj2)
session.commit()
models.py;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 09:54
# File : models.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
""
"""
1、安装pip3 install sqlalchemy ;
2、依赖于pymysql进行数据库连接;
3、并不支持修改表结构,仅支持在数据库修改字段后,再重新在此处修改;
"""
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, UniqueConstraint, Index
from sqlalchemy import create_engine Base = declarative_base() # 创建数据表;
class Users(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
extra = Column(String(16)) # __table_args = (
# UniqueConstraint('id', 'name', name='uix_id_name'),
# Index('ix_id_name', 'name', 'extra')
# ) # 数据库连接相关;
# engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com/flask_session?charset=utf8")
# Base.metadata.create_all(engine)
# 删除表;
# Base.metadata.drop_all(engine) # 向表中插入数据;
def init_db():
# 数据库连接相关;
engine = create_engine("mysql+pymysql://root:Tqtl913421411!@%*)@123.321.com:3306/flask_session?charset=utf8")
# 创建表;
Base.metadata.create_all(engine) def drop_db():
# 数据库连接相关;
engine = create_engine("mysql+pymysql://root:Tqtl911!@%*4321432)@123.321.com:3306/flask_session?charset=utf8")
# 删除表;
Base.metadata.drop_all(engine) if __name__ == '__main__':
init_db()
# drop_db()
10 SQLAlchemy框架组件使用
10.1 SQLAlchemy框架组件使用;
SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
MySQL-Python
mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql
mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector
mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
11 SQLAlchemy执行原生SQL
11.1 SQLAlchemy执行原生SQL语句操作;
- 基于SQLAlchemy写原生SQL(优势在于自带数据库连接池);
- 基于SQLAlchemy写ORM;
- DBUtils+pymysql创建连接池;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 11:05
# File : 3.执行原生SQL.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:@flask_session123456mysql.cuixiaozhao.com:3306/", max_overflow=5) # 执行SQL
cur = engine.execute(
"INSERT INTO hosts (host, color_id) VALUES ('1.1.1.22', 3)"
) # 新插入行自增ID
cur.lastrowid # 执行SQL
cur = engine.execute(
"INSERT INTO hosts (host, color_id) VALUES(%s, %s)", [('1.1.1.22', 3), ('1.1.1.221', 3), ]
) # 执行SQL
cur = engine.execute(
"INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)",
host='1.1.1.99', color_id=3
) # 执行SQL
cur = engine.execute('select * from hosts')
# 获取第一行数据
cur.fetchone()
# 获取第n行数据
cur.fetchmany(3)
# 获取所有数据
cur.fetchall()
12 上述内容总结
12.1 基于SQLALchemy实现数据库的增删改查;
12.2 单表操作;
12.3 多表操作;
13 SQLAlchemy创建表结构
13.1 使用SQLAlchemy;
- 安装 pip3 install sqlalchemy pymysql
14 SQLAlchemy实现基本增删改查(一)
14.1 基于SQLAlchemy实现基本的创建数据表操作;
增加;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 15:14
# File : 2.单表的增加操作.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
import models
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://fda!fda%*)@mysql.dfa.com:3306/flask_session?charset=utf8")
xxxx = sessionmaker(bind=engine)
session = xxxx() # 单条记录增加
# obj = models.Classes(name = "全栈1期")
# session.add(obj) # 多条记录增加;
objs = [
# models.Classes(name = '全栈2期'),
models.Classes(name='全栈3期'),
models.Classes(name='全栈4期'),
models.Classes(name='全栈5期'),
]
session.add_all(objs)
session.commit()
session.close()
查询;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 15:29
# File : 3.单表的查询操作.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models engine = create_engine("mysql+pymysql://fdafda!@%*)@fa.fda.com:3306/flask_session?charset=utf8") maker = sessionmaker(bind=engine)
session = maker()
# 查询; result = session.query(models.Classes).all()
# print(result)#[<models.Classes object at 0x10dcb2358>, <models.Classes object at 0x10dcb23c8>, <models.Classes object at 0x10dcb2438>, <models.Classes object at 0x10dcb24a8>, <models.Classes object at 0x10dcb2518>]
for item in result:
print(item.id, item.name)
session.commit()
session.close()
删除;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 15:33
# File : 4.单表的删除操作.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models engine = create_engine("mysql+pymysql://ffdfdaf!@%*)@fda.cuifdasxiaozhao.com:3306/flask_session?charset=utf8")
maker = sessionmaker(engine) session = maker()
# 删除
result = session.query(models.Classes).filter(models.Classes.id > 13).delete()
session.commit()
session.close()
修改;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 15:38
# File : 5.单表的修改操作.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models engine = create_engine("mysql+pymysql://root:Tfdasfda1!@%*)@123.45.67.89:3306/flask_session?charset=utf8")
maker = sessionmaker(engine) session = maker() # 更新操作;˚
session.query(models.Classes).filter(models.Classes.id > 0).update({models.Classes.name: models.Classes.name + ""},
synchronize_session=False)
# 尾部的参数决定了是进行字符串操作还是数学运算操作;
session.commit()
session.close()
15 SQLAlchemy实现基本增删改查(二)
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 15:38
# File : 5.单表的修改操作.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8")
maker = sessionmaker(engine) session = maker() # 更新操作;˚
session.query(models.Classes).filter(models.Classes.id > 0).update({models.Classes.name: models.Classes.name + ""},
synchronize_session=False)
# 尾部的参数决定了是进行字符串操作还是数学运算操作;
session.commit()
session.close()
16 SQLAlchemy小练习
16.1 小练习;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 16:15
# File : 7.练习.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine, text
import models engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8") maker = sessionmaker(bind=engine)
session = maker()
obj = models.Student(username='崔晓丝', password='', class_id=2)
session.add(obj) # 在学生表中找到崔晓丝;
obj1 = session.query(models.Student).filter(models.Student.username == '崔晓丝').first()
print(obj1) # <models.Student object at 0x108762a90> # 找到所有学生;
# 1、LOW B查询方式;
# objs = session.query(models.Student).all()
# for obj in objs:
# cls_obj = session.query(models.Classes).filter(models.Classes.id ==obj.class_id).first()
# print(obj.id,obj.username,obj.class_id,cls_obj.name)
# 2、主动连表操作;
objs = session.query(models.Student.id, models.Student.username, models.Classes.name).join(models.Classes, isouter=True).all()
print(objs) # 3、relationship引入;
objs2 = session.query(models.Student).all()
for item in objs2:
print(item.id,item.username,item.class_id,item.cls.name) session.commit()
session.close() # 4、全栈2期所有的学生
obj3 = session.query(models.Classes).filter(models.Classes.name =="全栈2期999").first() student_list = obj3.stus
for i in student_list:
print(i.id,i.username)
print("全栈2期所有的学生",student_list)
17 SQLAlchemy常见操作
17.1 SQLAlchemy常见操作;
- 分组
- 连表
- 组合
- 条件
- 通配符
- 限制
# 条件
ret = session.query(Users).filter_by(name='alex').all()
ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
from sqlalchemy import and_, or_
ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all()
ret = session.query(Users).filter(or_(Users.id < 2, Users.name == 'eric')).all()
ret = session.query(Users).filter(
or_(
Users.id < 2,
and_(Users.name == 'eric', Users.id > 3),
Users.extra != ""
)).all() # 通配符
ret = session.query(Users).filter(Users.name.like('e%')).all()
ret = session.query(Users).filter(~Users.name.like('e%')).all() # 限制
ret = session.query(Users)[1:2] # 排序
ret = session.query(Users).order_by(Users.name.desc()).all()
ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all() # 分组
from sqlalchemy.sql import func ret = session.query(Users).group_by(Users.extra).all()
ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).all() ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all() # 连表 ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all() ret = session.query(Person).join(Favor).all() ret = session.query(Person).join(Favor, isouter=True).all() # 组合
q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union(q2).all() q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union_all(q2).all() 常用操作
18 上述内容总结
18.1 表操作;
18.2 数据进行操作;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: SQLALchemy
# Software: PyCharm
# Time : 2018-09-22 19:10
# File : 1.总结.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
import models
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8")
xxxx = sessionmaker(bind=engine)
session = xxxx() session.add
session.add_all()
session.query(Users).all()
session.query(Users.id, Users.name).filter(User.name == 'alex')
session.query(Users.id, Users.name).filter_by(name='alex')
session.query(Users.id, Users.name).filter_by(name='alex').filter() session.query(Users.id, Users.name).filter(User.name == 'alex').update({}, 字符串)
session.query(Users.id, Users.name).filter(User.name == 'alex').update({}, 计算) session.query(Users.id, Users.name).filter(Users.name == 'alex').delete()
19 homework
第6章 章节六
01 内容概要
1.1 WTForms验证流程
1.2 SQLAlchemy下的lrelationship以及子查询;
02 内容回顾
2.1 315++面试题准备;
2.2 谈谈你对Python和其他语言的区别?
2.3 为什么要学习Python?
2.4 基本的数据类型-字符串、字典、元组、列表、集合、collections
2.5 函数:
-函数的参数传递的是什么?
-def func(a,b=[]):pass
-lambda 表达式
-列表生成式
-生成器表达式
-常见的内置函数:map、reduce、filter、zip、instance、type
2.6 回顾;
2.6.1 WTForms作用?
2.6.2 WTForms涉及到的作用点?哪里用到了?
- metaclass
- 封装:UnboundField
- _new__
- __mro__
- setattr
- type(...)
2.6.3 ORM和原生SQL比较?
2.6.4 你用过的ORM框架有哪些?Django ORM SQLAlchemy,所有的语言都有ORM;
2.6.5 DBFirst、CodeFIrst;
2.6.6 SQLAlchemy自带数据库连接池;
03 WTforms组件验证流程
04 SQLAlchemy操作补充
4.1 relationship帮助我们做跨表操作-增加和查询;
4.2 子查询;
05 homework
5.1 SQLAlchemy中设置表:引擎、编码;
5.2 Django中的DBFirst示例;
5.3 在Flask程序中应用SQLAlchemy;
第7章 章节七
01 内容概要
1.1 Flask内容扫尾-Flask目录创建;
1.2 Flask-script;
1.3 flask-sqlalchemy;
1.4 flask-migrate;
1.5 flask自定义组件;
1.6 其他-多app应用;
1.7 离线脚本&信号(blinker,相当于埋点,需要的时候触发执行即可);
02 内容回顾
2.1 谈谈你对Python和其他语言的区别?
2.1.1 编译型和解释性的区别;
2.1.2 解释型:Python、PHP
2.1.3 编译型:C 、C++
2.1.4 混合型:Java
2.2 为什么要学习Python?
2.2.1 简单易学;
2.2.2 生态圈比较强大;
2.2.3 发展趋势比较好,人工智能、数据分析;
2.2.4 还有很多...
2.3 Python中的数据类型?
- 字符串
- 字典
- 元组
- 列表
- 集合
- collections
2.4 函数
- 函数参数传递的是什么?
- def func(a,b=[]):pass
- lambda 表达式
- 列表生成式
- 生成器表达式(for i in range(1))
常见内置函数-map reduce filter zip instance type
2.5 生成器、迭代器、装饰器以及可迭代对象
- 迭代器-主要体现__next__方法;
- 生成器,迭代器的一种,一个函数存在yield关键字,生成器函数,函数执行,才是生成器,场景:range|xrange,redis取值,stark组件;
- 可迭代对象,一个类的内部实现__iter__方法且返回一个迭代器;WTForms中对form对象进行循环时候,显示form中包含的所有字段;列表、字典、元组;
- 装饰器,在不改变原函数代码的基础上,在执行前后进行定制操作;flask路由系统,csrf_token,Django内置的登录;flask_before_request,Django的缓存;
03 Flask-script组件
3.1 flask-script的作用;
- python manage.py runserver
- python manage.py 自定义命令
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 15:51
# File : manage.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from FullFlask import create_app
from flask_script import Manager app = create_app()
manager = Manager(app) @manager.command
def custom(arg):
print(arg) @manager.option('-n', '--name', dest='name')
@manager.option('-u', '--url', dest='url')
def cmd(name, url):
"""
自定义命令:
执行:python manage.py cmd -n cuixiaozhao -u http://cuixiaozhao.com
执行:python manage.py cmd --name cuixiaozhao --url http://cuixiaozhao.com
:param name:
:param url:
:return:
"""
print(name, url) if __name__ == '__main__':
# app.run()
manager.run()
04 FLask-SQLAlchemy组件应用(一)
4.1 基于SQLAlchemy进行查询数据;
4.2 Flask项目目录结构如下;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 15:54
# File : accounts.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org from flask import blueprints
from FullFlask import models ac = blueprints.Blueprint('ac', __name__) @ac.route('/login', methods=['GET', 'POST'])
def login():
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/FullFlask?charset=utf8")
maker = sessionmaker(bind=engine)
session = maker()
result = session.query(models.Users).all()
session.close()
print(
result) # [<FullFlask.models.Users object at 0x106123c88>, <FullFlask.models.Users object at 0x106123dd8>, <FullFlask.models.Users object at 0x106123a90>, <FullFlask.models.Users object at 0x1061239e8>] return 'Login it.'
05 Flask-SQLAlchemy组件应用(二)
5.1 SQLAlchemy组件应用二;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 16:37
# File : settings.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
class BaseConfig(object):
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/FullFlask?charset=utf8"
SQLALCHEMY_POOL_SIZE = 5
SQLALCHEMY_POOL_TIMEOUT = 30
SQLALCHEMY_POOL_RECYCLE = -1 # 追踪对象的修改并且发送信号;
SQLALCHEMY_TRACK_MODIFICATIONS = False class ProductionConfig(BaseConfig):
pass class DevelopmentConfig(BaseConfig):
pass class TestConfig(BaseConfig):
pass """
小结:
1、flask-sqlalchemy的作用:将SQLAlchemy相关的所有功能都封装到db=flask_sqlalchemy.SQLAlchemy()对象中;
-创建表;
class Users( ):
pass -操作表;
db.session """
06 Flask-SQLAlchemy组件应用(三)
6.1 pip3 install flask-sqlalchemy安装;
6.2 离线脚本的使用;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 17:08
# File : drop_table.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
""
"""
1、Web运行时候,flask程序运行起来,用户通过浏览器访问;
2、离线脚本,即自定义的一个py文件+使用flask中定义好的功能;
"""
from FullFlask import db
from FullFlask import create_app
from FullFlask import models app = create_app()
with app.app_context():
# db.drop_all()
# db.create_all()
data = db.session.query(models.Users).all()
print(data)
07 Flask-SQLAlchemy组件应用总结
7.1 在__init__.py文件中创建db对象;
7.2 在__init__.py中的create_app函数中让将app传入到app中;
7.3 写配置文件,将连接字符串定义在配置文件中;
7.4 定义models.py文件,导入第一步的db;
7.5 创建数据库表,编写离线脚本:drop_table.py;
7.6 在视图函数中,使用SQLAlchemy操作数据库;
08 SQLAlchemy创建session的两种方式
8.1 两种创建session的方式;
- 基于scopted_sessionn进行session = scopted_session(maker)创建
- 基于传统方式创建;
- PS:flask-session默认使用scopted_session创建,不再担心多线程问题;
09 Flask-Migrate组件
9.1 flask-migrate:做数据库迁移,依赖如下包:
- flask-script
- flask-sqlalchemy
9.2 生成数据库迁移命令;
- python manage.py db init
- python manage.py db migrate
- python manage.py db upgrade
10 Flask自定义拓展
11 Flask多app应用
11.1 Flask的多app应用;
本质就是对URL的分发和处理;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 21:32
# File : 多app应用.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware from werkzeug.serving import run_simple app01 = Flask('app01')
app02 = Flask('app02') dm = DispatcherMiddleware(app01, {
'/app02': app02,
}) if __name__ == '__main__':
run_simple('localhost', 5000, dm)
12 Flask信号blinker
12.1 汽车赛道举例;
12.2 pip3 install blinker# 安装信号;
12.3 常见信号;
# Core signals. For usage examples grep the source code or consult
# the API documentation in docs/api.rst as well as docs/signals.rst
template_rendered = _signals.signal('template-rendered')
before_render_template = _signals.signal('before-render-template')
request_started = _signals.signal('request-started')
request_finished = _signals.signal('request-finished')
request_tearing_down = _signals.signal('request-tearing-down')
got_request_exception = _signals.signal('got-request-exception')
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')
appcontext_pushed = _signals.signal('appcontext-pushed')
appcontext_popped = _signals.signal('appcontext-popped')
message_flashed = _signals.signal('message-flashed')
12.4 flask_signals.py;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: FullFlask
# Software: PyCharm
# Time : 2018-09-23 21:48
# File : Flask-signal.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from flask import Flask, signals app = Flask(__name__) def func1(*args, **kwargs):
print('触发信号:request_started') def func2(*args, **kwargs):
print('触发信号:request_started') signals.request_started.connect(func1)
signals.appcontext_pushed.connect(func2) @app.route('/login')
def login():
return 'Login' if __name__ == '__main__':
app.run()
13 Flask信号和before_request的区别
13.1 brefore_request,可以控制请求是否可以继续往后执行;
13.2 信号,在原来的基础增加额外的操作和值;
14 内容总结和作业
14.1 Flask写完了,如何使用Flask做出个项目;
14.2 代码发布系统,比如RabbitMQ、saltstack、Celery;
14.3 面试相关:
14.3.1 手写Flask内置HelloWorld!
14.3.2 Flask和其他框架的区别?
14.3.3 Flask内置组件:
- 配置
- 路由
- 视图
- 模板
- session
- 闪现
- 蓝图
- 中间件
- 特殊装饰器
14.3.4 Flask第三方组件:
- flask-session——默认session放在签名的cookie中,使用Redis存储session信息;
- flask-SQLAlchemy;
- flask-migrate;
- flask-script;
- flask-....还有很多!
- blinker
14.3.5 公共组件:
- WTForms
- DBUtils
- SQLAlchemy
14.3.6 自定义Flask组件:
- auth,参考flask-login组件
14.3.7 上下文管理机制:
- 为什么使用LocalStack对Local对象进行操作?目的是要将Local中的值;
14.3.8 Flask项目目录维护;