FlaskWeb开发从入门到放弃(二)

第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

FlaskWeb开发从入门到放弃(二)

问题一: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

FlaskWeb开发从入门到放弃(二)

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 汽车赛道举例;

FlaskWeb开发从入门到放弃(二)

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项目目录维护;

上一篇:new和malloc的区别


下一篇:MongoDB的安装及配置