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
- 问题一: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项目目录维护;
FlaskWeb开发从入门到放弃(二)的更多相关文章
- hive从入门到放弃(二)——DDL数据定义
前一篇文章,介绍了什么是 hive,以及 hive 的架构.数据类型,没看的可以点击阅读:hive从入门到放弃(一)--初识hive 今天讲一下 hive 的 DDL 数据定义 创建数据库 CREAT ...
- python全栈开发从入门到放弃之初识面向对象
面向过程 VS 面向对象 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了写程序的复 ...
- python全栈开发从入门到放弃之面向对象的三大特性
组合 class Course: def __init__(self,name,period,price): self.name = name self.period = period self.pr ...
- python全栈开发从入门到放弃之socket网络编程基础
网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...
- python全栈开发从入门到放弃之socket并发编程多进程
1.1 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程 ...
- python全栈开发从入门到放弃之socket并发编程多线程
一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二 开启线程的两种方式 from threadi ...
- python全栈开发从入门到放弃之网络基础
一.操作系统基础 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才 ...
- Flask Web开发从入门到放弃(一)
第1章 章节一 01 内容概要 02 内容回顾 03 路飞学城之加入购物车 04 路飞学城之结算 05 路飞学城之立即支付 06 路飞学城之后续计划 07 Flask框架简介和快速使用 08 FLas ...
- Go语言从入门到放弃(二) 优势/关键字
本来这里是写数据类型的,但是规划了一下还是要一步步来,那么本篇就先介绍一下Go语言的 优势/关键字 吧 本章转载 <The Way to Go>一书 Go语言起源和发展 Go 语 言 起 ...
随机推荐
- webstorn中的vue文件识别es6代码
webstorn中的vue文件识别es6代码 1.webstorm中es6语法报错,解决方法: 打开 Settings => Languages & Frameworks => J ...
- JAVA 线程状态转换图示及说明
线程状态类型 新建状态(New):新创建了一个线程对象. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获取C ...
- 【题解】洛谷P3205【HNOI2010】合唱队
洛谷 P3205:https://www.luogu.org/problemnew/show/P3205 复习区间DPing 思路 把理想队列拆分成 第一个和后面几个 划分成求后面几个的理想队列 最后 ...
- 微信小程序分包加载
分包加载 某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载. 在构建小程序分包项目时,构建会输出一个或多个功能的分包,其中每个分包小程序必定含有一个主 ...
- android(eclipse)编程中常见的java问题总结(四)
0:java流: 流是具有方向的 在文件操作中java流分为字节流:Filereader和Filewriter字符流:FileOutputStream,FileInputSream 例如在 ...
- mui的事件实现(持续更新)
长按事件: mui('.mui-scroll').on('longtap', '.index-tab-item', function(e) { alert("长按生效") }); ...
- 史上最简单的 SpringCloud 教程 | 第十四篇: 服务注册(consul)
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springcloud/2017/07/12/sc14-consul/ 本文出自方志朋的博客 这篇文章主要介绍 s ...
- 协议类接口 - I2C
一.12c总线概述 I2C( Inter-Integrated Circuit,又称IIC)总线是一种串行总线,用 于连接微控制器及其外围设备,硬件图非常简单:一条串行数据线(SDA),一条串行时钟线 ...
- 【转】opatch学习
[转自:https://yq.aliyun.com/articles/28007,仅作学习用途] Opatch 是oracle公司开发的安装,卸载,检测patch冲突的工具,管理oracle所有已经安 ...
- 删除Navicat在注册表信息
@echo offecho 正在删除navicat注册表REG DELETE HKEY_CURRENT_USER\Software\PremiumSoft\Data /fREG DELETE HKEY ...