sqlalchemy
sqlalchemy-postgresql使用数据库连接池
---用create_engine原生连接池写法
from psycopg2 import pool from psycopg2 import Error from sqlalchemy import text, create_engine ENGINE_ = create_engine( "postgresql://{}:{}@{}:{}/{}".format( "testdb_name", "testdb_pwd", "localhost", "5432", "test_db_table_name" ), pool_size=20, max_overflow=10, echo=False, # 这个参数,是打印sql执行日志 pool_recycle=3600 ) def create_engine_pool_use(sql_statement): """ 用sqlalchemy原生的连接池,来操作数据库 :param sql_statement: 传入的sql语句字符串 :return: """ engine_conn = ENGINE_.connect() result_ = engine_conn.execute(text(sql_statement)) fetch_data = result_.fetchall() engine_conn.close() return fetch_data
# 使用方法。调用一次create_engine_pool_use方法,就是从连接池拿到一个连接,连接池只需要实例化一次
ret_db = create_engine_pool_use("select name from info_tb")
print(ret_db)
---用psycopg2封装连接池
class PostgresSQLPool: def __init__(self): """ 初始化配置 """ self.recursion_dict = {} try: self.connectPool = pool.ThreadedConnectionPool( 2, 10, host=InitConfig.POSTGRES_HOST, port=InitConfig.POSTGRES_PORT, user=InitConfig.POSTGRES_USER, password=InitConfig.POSTGRES_PWD, database=InitConfig.POSTGRES_DB, # 如下参数配置,是最底层被继承的Connect类的配置,适用于任何继承它的类 keepalives_idle=10, # 如果该连接闲置10s,就开始发送侦探包,轮训该连接是否有回应 keepalives_count=3, # 发送3个侦探包 keepalives_interval=5 # 每次发送的侦探包,会等待5s。如果该连接 # 闲置了10s,轮训了它3次,每次等待时间是5s,之后,它还是没有回应,就切断该连接 ) except (Exception, Error) as error: print("Error while connecting to PostgreSQL", error) raise EnvironmentError(str(error)) def get_connect(self): """ 获取连接池连接对象 :return: """ conn = self.connectPool.getconn() cursor = conn.cursor() return conn, cursor def close_connect(self, conn, cursor): """ 把从连接池拿到的连接,返回给连接池 :param conn: :param cursor: :return: """ cursor.close() self.connectPool.putconn(conn) def close_all(self): """ close all connection, if you call .close_all make sure your code can deal with it :return: """ self.connectPool.closeall() def select_one(self, sql): """ 获取一条查询结果 :param sql: sql sentence str :return: """ conn, cursor = self.get_connect() cursor.execute(sql) result = cursor.fetchone() self.close_connect(conn, cursor) return result def select_all(self, sql): """ 获取所有查询结果 :param sql: sql sentence str type :return: """ conn, cursor = self.get_connect() cursor.execute(sql) result = cursor.fetchall() self.close_connect(conn, cursor) return result def execute_sql(self, sql_sentence, args=None): """ execute add,delete,edit function :param sql_sentence: :param args: :return: """ conn, cursor = self.get_connect() try: res = cursor.execute(sql_sentence, args) conn.commit(conn, cursor) self.close_connect(conn, cursor) return res except Exception as e: conn.rollback() raise ValueError("execute sql error. %s" % str(e)) # 这里下面就是递归查询节点之间的调用关系方法,之前的项目中用到了,贴进来备忘 @staticmethod def split_host_dep(tp_row): """ depend each row of database selected to split host id、name、type and dep id、name、type :param tp_row: :return: """ try: host_key = "**".join(tp_row[3:]) dep_value = "**".join(tp_row[:3]) except TypeError: # if field value selected is None, then replace it as "" each_key = ["" if each_field_value is None else each_field_value for each_field_value in tp_row] host_key = "**".join(each_key[3:]) dep_value = "**".join(each_key[:3]) return host_key, dep_value def recursion_db_select(self, host_key): """ 递归用sql语句查询,调试完成。 :param host_key:查询关键字,string:id**name**type :return: """ pdc_value = host_key.split("**")[0] sql_str = "select dep_pdc, dep_pdc_name, dep_pdc_type " \ " from" \ " tb_pdc_rel where host_pdc='%s';" % pdc_value ret = self.select_all(sql_str) if ret: # 如果有字节点,就继续递进去,查询字节点 for each_row in ret: # host_value = each_row[0] host_value = "**".join(each_row) # 如果字节点不在存储最终数据的字典里,就创建一组键值对,键是id,值是空集合 if host_key not in self.recursion_dict: self.recursion_dict[host_key] = set() # 把当前递归层的元素,保存到最终存储的数据字典中 self.recursion_dict[host_key].add(host_value) # 开始递到下一层 ret_dic = self.recursion_db_select(host_value) if ret_dic: # 如果有归回来的返回值,更新数据字典 self.recursion_dict.update(ret_dic) return self.recursion_dict def get_all_data(self): """ get database all data :return: """ sql_all_data = "select dep_pdc, dep_pdc_name, dep_pdc_type, " \ "host_pdc, host_pdc_name, host_pdc_type from" \ " tb_pdc_rel;" db_all_data = self.select_all(sql_all_data) # build all data to dict, key is host id**name**type, value is list of # dep id**name**type dic_obj = {} for each_key in db_all_data: host_key, dep_value = self.split_host_dep(each_key) if host_key not in dic_obj: dic_obj[host_key] = [] dic_obj[host_key].append(dep_value) # rebuild data to dict, the key is host_pdc, the value is list # include all dep_pdc items return dic_obj def splice_id_name_type(self, id_value): """ splice host id**name**type from database selected with the arg from for end transfer :param id_value: :return: """ sql = "select host_pdc, host_pdc_name, host_pdc_type from tb_pdc_rel" \ " where host_pdc='%s';" % id_value host_values = self.select_one(sql) if not host_values: raise ValueError("could not find any data from database") host_value = "**".join(host_values) return host_value def get_for_end_item_tree(self, host_value): """ get all related data to prepare to render on html page :param host_value:host id**name**value from str :return: """ dic_obj = self.get_all_data() recur_obj = RecursionTest() ret_dic = recur_obj.search_host_pdc(host_value, dic_obj) return ret_dic
# 使用方法
psql_obj = PostgresSQLPool()
ret = psql_obj.select_one("select name from info_table where id=10")
print(ret)
ret_all_db = psql_obj.select_all("select id, name from info_table")
print(ret_all_db)

1 s8day128 2 3 内容回顾: 4 1. flask和django区别? 5 - 相同: 6 - 基于wsgi 7 - 不同: 8 - 传值方式 9 - 组件: 10 - flask少 11 - django多 12 13 2. flask上下文管理是如何实现? 14 - 前提:记得不太清除了,应该是xxx; 前两天恰好刚看的。 15 - 流程: 16 - 请求刚进来,RequestContext(request,session)、AppContext(app,g) -> LocalStack -> Local 17 - 视图处理,LocalProxy -> 偏函数 -> LocalStack -> Local 18 - 请求结束,sava_session -> LocalStack.pop() 19 20 3. Local作用? 21 - 用于保存 22 - 请求上下文对象 23 - app上下文对象 24 - 并且可以做到“线程”间的数据隔离。 25 26 线程:threading.local 27 协程:greenlet.get_current as get_ident 28 29 30 4. LocalStack作用? 31 - 将Local中保存的数据维护成一个栈 32 33 { 34 1432: { stack:[ctx,ctx,ctx,] } 35 } 36 37 5. Flask内置功能 38 - 配置 39 - 路由 40 - 视图 41 - 模板 42 - session 43 - 蓝图 44 - 闪现 45 - 装饰器 46 - 中间件 47 48 6. 第三方组件: 49 - Flask: 50 - flask-session,将原来保存在cookie中的session数据,放到redis/memcache/文件/数据库中。 51 - 公共: 52 - DBUtils,数据库连接池 53 - wtforms,做表单验证+生成HTML标签 54 55 今日内容: 56 1. 面向对象相关 57 __mro__ 58 metaclass 59 60 2. wtforms 61 62 3. SQLALchemy/flask-sqlalchemy 63 64 4. 其他 65 - flask-script 66 - flask-migrate 67 - 多app应用 68 - 离线脚本 69 70 内容详细: 71 1. 面向对象相关 72 1. __mro__,找到当前类寻找属性的顺序。 73 class A(object): 74 pass 75 76 77 class B(A): 78 pass 79 80 81 class C(object): 82 pass 83 84 class D(B,C): 85 pass 86 87 print(D.__mro__) 88 89 2. __dict__ 90 class Foo(object): 91 CITY = 'bj' 92 def __init__(self,name,age): 93 self.name = name 94 self.age = age 95 def func(self): 96 pass 97 98 # print(Foo.CITY) 99 # print(Foo.func) 100 print(Foo.__dict__) 101 102 obj1 = Foo('oldboy',54) 103 print(obj1.__dict__) 104 105 3. metaclass 106 # 1. 创建类的两种方式 107 class Foo(object): 108 CITY = "bj" 109 110 def func(self,x): 111 return x + 1 112 113 Foo = type('Foo',(object,),{'CITY':'bj','func':lambda self,x:x+1}) 114 115 116 117 # 2. 类由自定义type创建 118 # 类由type创建,通过metaclass可以指定当前类由那一个type创建。 119 """ 120 class MyType(type): 121 def __init__(self,*args,**kwargs): 122 print('创建类之前') 123 super(MyType,self).__init__(*args,**kwargs) 124 print('创建类之后') 125 126 class Foo(object,metaclass=MyType): # 当前类,由type类创建。 127 CITY = "bj" 128 def func(self, x): 129 return x + 1 130 """ 131 # 3. 类的继承 132 # 类的基类中指定了metaclass,那么当前类也是由metaclass指定的类来创建当前类。 133 """ 134 class MyType(type): 135 def __init__(self,*args,**kwargs): 136 print('创建类之前') 137 super(MyType,self).__init__(*args,**kwargs) 138 print('创建类之后') 139 140 class Foo(object,metaclass=MyType): # 当前类,由type类创建。 141 CITY = "bj" 142 def func(self, x): 143 return x + 1 144 145 class Bar(Foo): 146 pass 147 """ 148 149 150 # ################################## 变 ################################## 151 """ 152 class MyType(type): 153 def __init__(self,*args,**kwargs): 154 print('创建类之前') 155 super(MyType,self).__init__(*args,**kwargs) 156 print('创建类之后') 157 158 Base = MyType('Base',(object,),{}) 159 # class Base(object,metaclass=MyType): 160 # pass 161 162 class Foo(Base): 163 CITY = "bj" 164 def func(self, x): 165 return x + 1 166 """ 167 # ################################## 变 ################################## 168 """ 169 class MyType(type): 170 def __init__(self,*args,**kwargs): 171 print('创建类之前') 172 super(MyType,self).__init__(*args,**kwargs) 173 print('创建类之后') 174 175 def with_metaclass(arg): 176 return MyType('Base',(arg,),{}) # class Base(object,metaclass=MyType): pass 177 178 class Foo(with_metaclass(object)): 179 CITY = "bj" 180 def func(self, x): 181 return x + 1 182 """ 183 184 # ######################################################## 实例化 ######################################################## 185 class MyType(type): 186 def __init__(self,*args,**kwargs): 187 super(MyType,self).__init__(*args,**kwargs) 188 189 class Foo(object,metaclass=MyType): # 当前类,由type类创建。 190 pass 191 192 193 """ 194 0. Mytype的__init__ 195 obj = Foo() 196 1. MyType的__call__ 197 2. Foo的__new__ 198 3. Foo的__init__ 199 """ 200 201 总结: 202 1. 默认类由type实例化创建。 203 2. 某个类指定metaclass=MyType,那么当前类的所有派生类都由于MyType创建。 204 3. 实例化对象 205 - type.__init__ 206 207 - type.__call__ 208 - 类.__new__ 209 - 类.__init__ 210 211 212 2. wtforms实现流程 213 214 实例化流程: 215 class LoginForm(Form): 216 name = StringField(正则=[验证规则1,验证规则1,],插件=Input框) 217 pwd = StringField(正则=[验证规则1,验证规则1,],插件=Password框) 218 219 220 作业:找验证流程 221 222 223 相关面试题: 224 a. Python基础部分,哪些比较重要? 225 - 反射 226 - cbv 227 - django 配置文件 228 - wtforms中 229 class Form(with_metaclass(FormMeta, BaseForm)): 230 231 Meta = DefaultMeta 232 233 def __init__(self, formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs): 234 235 ... 236 """ 237 self._fields = { 238 'name': simple.StringField(实例化), 239 'pwd': simple.PasswordField(), 240 } 241 """ 242 for name, field in iteritems(self._fields): 243 # Set all the fields to attributes so that they obscure the class 244 # attributes with the same names. 245 setattr(self, name, field) 246 ... 247 obj = Form() 248 obj.name 249 - 装饰器 250 - flask路由 /装饰器 251 - 认证 252 - csrf 253 254 - 生成器、迭代器 255 256 257 - 面向对象 258 - 继承、封装、多态 259 - 特殊功能: 260 - 双下划线的方法 261 - __mro__ 262 class FormMeta(type): 263 def __call__(cls, *args, **kwargs): 264 ... 265 # Create a subclass of the 'class Meta' using all the ancestors. 266 if cls._wtforms_meta is None: 267 bases = [] 268 # LoginForm,Form,BaseForm,object 269 for mro_class in cls.__mro__: 270 if 'Meta' in mro_class.__dict__: 271 bases.append(mro_class.Meta) 272 273 cls._wtforms_meta = type('Meta', tuple(bases), {}) 274 - __dict__ 275 - dir 276 - dict 277 - __new__ ,实例化但是没有给当前对象 278 - wtforms,字段实例化时返回:不是StringField,而是UnboundField 279 def __new__(cls, *args, **kwargs): 280 if '_form' in kwargs and '_name' in kwargs: 281 return super(Field, cls).__new__(cls) 282 else: 283 return UnboundField(cls, *args, **kwargs) 284 - rest framework ,many=True 285 - __call__ 286 - flask请求的入口 287 - 字段生成标签时:字段.__str__ => 字段.__call__ => 插件.__call__ 288 - __iter__ 289 pass 290 291 - metaclass 292 - 作用:用于指定使用哪个类来创建当前类 293 - 场景:在类创建之前定制操作 294 示例:wtforms中,对字段进行排序。 295 296 297 3. SQLAchemy,ORM框架。 298 问题:什么是ORM? 299 关系对象映射 300 类 -> 表 301 对象 -> 记录(一行数据) 302 303 当有了对应关系之后,不再需要编写SQL语句,取而代之的是操作:类、对象。 304 ORM: models.User.objects.filter(id__gt=1,type__name='技术部') 305 306 SQL: 307 select 308 id, 309 name, 310 age, 311 email 312 from user left join type on user.type_id = type.id 313 314 问题: ORM和原生SQL哪个好? 315 316 问题: 概念 317 db first,根据数据库的表生成类 318 django 319 python manage.py inspectdb 320 code first,根据类创建数据库表; 321 django: 322 python manage.py makemigrations 323 python manage.py migrate 324 325 326 问题:ORM是怎么实现? 327 DDD中: unit of work 328 329 330 SQLALchemy,是一个基于python实现的ORM框架。 331 1. 基于SQLALchemy写原生SQL 332 - SQLAclchemy连接池 333 import time 334 import threading 335 import sqlalchemy 336 from sqlalchemy import create_engine 337 from sqlalchemy.engine.base import Engine 338 339 engine = create_engine( 340 "mysql+pymysql://root:123@127.0.0.1:3306/t1?charset=utf8", 341 max_overflow=0, # 超过连接池大小外最多创建的连接 342 pool_size=5, # 连接池大小 343 pool_timeout=30, # 池中没有线程最多等待的时间,否则报错 344 pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收(重置) 345 ) 346 347 348 def task(arg): 349 conn = engine.raw_connection() 350 cursor = conn.cursor() 351 cursor.execute( 352 "select * from t1" 353 ) 354 result = cursor.fetchall() 355 cursor.close() 356 conn.close() 357 358 359 for i in range(20): 360 t = threading.Thread(target=task, args=(i,)) 361 t.start() 362 - DBUtils+pymysql 做连接池 363 2. 基于SQLALchemy写ORM 364 365 models.py 366 367 #!/usr/bin/env python 368 # -*- coding:utf-8 -*- 369 from sqlalchemy.ext.declarative import declarative_base 370 from sqlalchemy import Column, Integer, String, UniqueConstraint, Index 371 from sqlalchemy import create_engine 372 373 Base = declarative_base() 374 375 # 创建单表 376 class Users(Base): 377 __tablename__ = 'users' 378 id = Column(Integer, primary_key=True,autoincrement=True) 379 name = Column(String(32)) 380 extra = Column(String(16)) 381 382 383 # 数据库连接相关 384 # engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/s8day128db?charset=utf8") 385 # 创建表 386 # Base.metadata.create_all(engine) 387 # 删除表 388 # Base.metadata.drop_all(engine) 389 390 app.py 391 import models 392 from sqlalchemy.orm import sessionmaker 393 from sqlalchemy import create_engine 394 395 engine =create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/s8day128db?charset=utf8") 396 XXXXXX = sessionmaker(bind=engine) 397 session = XXXXXX() 398 399 400 401 obj1 = models.Users(name="alex", extra='sb') 402 obj2 = models.Users(name="alex", extra='db') 403 session.add(obj1) 404 session.add(obj2) 405 406 407 session.commit() 408 409 使用: 410 安装: pip3 install sqlalchemy 411 412 413 1. 表操作 414 #!/usr/bin/env python 415 # -*- coding:utf-8 -*- 416 from sqlalchemy.ext.declarative import declarative_base 417 from sqlalchemy import Column, Integer, String, UniqueConstraint, Index,DateTime,ForeignKey 418 from sqlalchemy import create_engine 419 import datetime 420 Base = declarative_base() 421 422 class Classes(Base): 423 __tablename__ = 'classes' 424 id = Column(Integer, primary_key=True,autoincrement=True) 425 name = Column(String(32),nullable=False,unique=True) 426 427 class Student(Base): 428 __tablename__ = 'student' 429 id = Column(Integer, primary_key=True, autoincrement=True) 430 username = Column(String(32), nullable=False,index=True) 431 password = Column(String(64), nullable=False) 432 ctime = Column(DateTime,default=datetime.datetime.now) 433 class_id = Column(Integer, ForeignKey("classes.id")) 434 435 class Hobby(Base): 436 __tablename__ = 'hobby' 437 id = Column(Integer, primary_key=True) 438 caption = Column(String(50), default='篮球') 439 440 class Student2Hobby(Base): 441 __tablename__ = 'student2hobby' 442 id = Column(Integer, primary_key=True, autoincrement=True) 443 student_id = Column(Integer, ForeignKey('student.id')) 444 hobby_id = Column(Integer, ForeignKey('hobby.id')) 445 446 __table_args__ = ( 447 UniqueConstraint('student_id', 'hobby_id', name='uix_student_id_hobby_id'), 448 # Index('ix_id_name', 'name', 'extra'), 449 ) 450 451 def init_db(): 452 # 数据库连接相关 453 engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/s8day128db?charset=utf8") 454 # 创建表 455 Base.metadata.create_all(engine) 456 def drop_db(): 457 engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/s8day128db?charset=utf8") 458 # 删除表 459 Base.metadata.drop_all(engine) 460 461 if __name__ == '__main__': 462 # drop_db() 463 init_db() 464 465 2. 数据进行操作 466 467 第一步: 468 增 469 删 470 改 471 查 472 473 第二步: 474 复杂查询条件 475 分组 476 排序 477 连表 478 分页 479 组合union /union all 480 481 482 PS: commit 483 484 参考博客:http://www.cnblogs.com/wupeiqi/articles/8259356.html 485 486 487 作业: 488 1. wtforms实例化过程 489 2. wtforms验证流程(钩子函数到底如何实现?) 490 3. SQLALchemy表+基本操作 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

1 s8day129 2 3 内容回顾: 4 1. 面试题准备 5 a. 谈谈你对Python和其他语言的区别? 6 b. 为什么要学python? 7 c. 数据类型: 8 - 字符串 9 - 字典 10 - 元组 11 - 列表 12 - 集合 13 - collections 14 d. 函数 15 - 函数参数传递的是什么? 16 - def func(a,b=[]):pass 17 - lambda 表达式 18 - 列表生成式 [] 19 - 生成器表达式 (for i in range(1)) 20 - 题: 21 val = [lambda :i+1 for i in range(10)] 22 val[0] 23 data = val[0]() 24 print(data) 25 - 常见内置函数: 26 - map 27 - reduce 28 - filter 29 - zip 30 - instance 31 - type 32 - 33 - 生成器、迭代器、装饰器 34 2. 回顾 35 - wtforms 36 - SQLALchemy 37 38 问题: 39 a. wtforms作用? 40 b. wtforms涉及到的知识点?哪里用了? 41 - metaclass 42 - 封装:UnboundField 43 - __new__ 44 - __mro__ 45 - setattr 46 - type(...) 47 c. ORM和原生SQL比较? 48 49 d. 你用过的ORM框架有哪些? 50 51 e. SQLAlchemy 52 - 数据库连接池 53 - 原生SQL 54 - ORM 55 - 表操作 56 - 默认值 57 - 索引(联合索引,想要命中必须遵循“最左前缀”的规则) 58 - sqlalchemy中设置表: 59 - 引擎 60 - 编码 61 - 记录操作 62 - 增删改查 63 64 65 今日内容: 66 1. wtforms验证流程 67 68 """ 69 处理插入新数据的视图: 70 GET请求: 71 form = Form() 72 POST请求: 73 form = From(formdata=表单提交的数据) 74 form.validate() 75 76 处理更新数据的视图: 77 GET请求: 78 查出obj, 保存住在后续POST请求还要用 79 form = Form(obj = obj) 80 POST请求 81 form = Form(formdata=表单提交的数据,obj=obj) 82 form.validate() 83 84 其他情况视图: 85 form = Form(data={ .. }) 86 # data作为表单的默认value 87 """ 88 89 90 2. sqlalchemy 91 - relationship 92 - 子查询 93 94 问题: 95 1. sqlalchemy中设置表:引擎、编码 96 2. django的db first示例 97 98 99 内容详细: 100 1. wtforms验证流程 101 102 103 104 2. SQLAlchemy 105 - relationship作用?增加和查询 106 107 108 一对多: 109 class UserType(Base): 110 __tablename__ = 'usertype' 111 id = Column(Integer, primary_key=True) 112 caption = Column(String(50), default='管理员') 113 114 115 class Person(Base): 116 __tablename__ = 'person' 117 nid = Column(Integer, primary_key=True) 118 name = Column(String(32), index=True, nullable=True) 119 hobby_id = Column(Integer, ForeignKey("usertype.id")) 120 121 # 与生成表结构无关,仅用于查询方便 122 hobby = relationship("UserType", backref='pers') 123 124 数据添加: 125 session.add(UserType(caption='超级管理员')) 126 session.commit() 127 128 session.add(Person(name='翔龙',hobby_id=1)) 129 session.commit() 130 131 132 session.add(Person(name='小韩',hobby=UserType(cation='VVIP'))) 133 session.commit() 134 135 数据查询: 136 正向操作: 137 obj = session.query(Person).filter(Person.nid==2).first() 138 obj.hobby.caption 139 反向操作: 140 obj = session.query(UserType).filter(UserType.id==1).first() 141 obj.pers 142 多对多: 143 class User2Hobby(Base): 144 __tablename__ = 'user2hobby' 145 id = Column(Integer, primary_key=True, autoincrement=True) 146 hobby_id = Column(Integer, ForeignKey('hobby.id')) 147 user_id = Column(Integer, ForeignKey('user.id')) 148 149 150 class Hobby(Base): 151 __tablename__ = 'hobby' 152 id = Column(Integer, primary_key=True) 153 title = Column(String(64), unique=True, nullable=False) 154 155 # 与生成表结构无关,仅用于查询方便 156 users = relationship('User', secondary='user2hobby', backref='hbs') 157 158 159 class User(Base): 160 __tablename__ = 'user' 161 162 id = Column(Integer, primary_key=True, autoincrement=True) 163 name = Column(String(64), unique=True, nullable=False) 164 165 166 添加数据: 167 session.add(Hobby(title='篮球')) 168 session.commit() 169 170 session.add(User(name='梅凯')) 171 session.commit() 172 173 session.add(User2Hobby(hobby_id=1,user_id=1)) 174 session.commit() 175 176 177 obj = Hobby(title='篮球') 178 obj.servers = [User(name='王岩'),User(name='晓梅')] 179 session.add(obj) 180 session.commit() 181 182 183 obj = User(title='俊杰') 184 obj.hbs = [Hobby(title='翔龙'),Hobby(title='兴隆')] 185 session.add(obj) 186 session.commit() 187 查询: 188 obj = session.query(User).filter(User.id==2).first() 189 obj.hbs 190 191 obj = session.query(Hobby).filter(Hobby.id==2).first() 192 obj.users 193 194 - SQL 195 196 a. 197 select * from A where id in (select age from B) 198 b. 199 select 200 id, 201 name, 202 1 203 from A 204 205 206 select 207 id, 208 name, 209 1, 210 (select max(id) from B) as b 211 from A 212 213 214 215 select 216 id, 217 name, 218 1, 219 (select max(id) from B where B.xid=A.id) as b 220 from A 221 222 +----+---------------+ 223 | id | name | 224 +----+---------------+ 225 | 1 | 全栈1期099 | 226 | 2 | 全栈2期099 | 227 +----+---------------+ 228 229 +----+---------+ 230 | id | caption | xid 231 +----+---------+ 232 | 1 | 篮球 | 1 233 | 2 | 球 | 1 234 +----+---------+ 235 236 subqry = session.query(func.count(Server.id).label("sid")).filter(Server.id == Group.id).correlate(Group).as_scalar() 237 result = session.query(Group.name, subqry) 238 """ 239 SELECT 240 `group`.name AS group_name, 241 (SELECT count(server.id) AS sid FROM server WHERE server.id = `group`.id) AS anon_1 242 FROM `group` 243 """ 244 245 246 247 # 也可以使用原生SQL 248 """ 249 # 查询 250 cursor = session.execute('select * from users') 251 result = cursor.fetchall() 252 253 # 添加 254 cursor = session.execute('insert into users(name) values(:value)',params={"value":'wupeiqi'}) 255 session.commit() 256 print(cursor.lastrowid) 257 """ 258 259 260 扩展: 261 select 262 id, 263 name, 264 1, 265 (select max(id) from B where B.xid=A.id) as b # 生物课 266 (select max(id) from B where B.xid=A.id) as b # 物理课 267 from A 268 269 where 270 生物课 》 物理课 271 272 273 复习: 274 http://www.cnblogs.com/wupeiqi/articles/5729934.html 275 276 http://www.cnblogs.com/wupeiqi/articles/5748496.html 277 278 279 280 281 作业: 282 283 问题: 284 1. sqlalchemy中设置表:引擎、编码 285 2. django的db first示例 286 3. 在基于蓝图的Flask程序应用SQLAlchemy,示例:用户登录 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
参详博客地址:点这里
先把地方霸占着
sqlalchemy数据增删改查以及创建表和删除表

1 from sqlalchemy.ext.declarative import declarative_base 2 from sqlalchemy import Column, Integer, String, UniqueConstraint, ForeignKey, Index, DateTime 3 from sqlalchemy import create_engine 4 from sqlalchemy.orm import relationship 5 import datetime 6 7 Bar = declarative_base() 8 9 10 class Classes(Bar): 11 __tablename__ = 'class' 12 id = Column(Integer, primary_key=True, autoincrement=True) 13 cname = Column(String(20), nullable=False, unique=True) 14 15 16 class Student(Bar): 17 __tablename__ = 'student' 18 id = Column(Integer, primary_key=True, autoincrement=True) 19 sname = Column(String(20), nullable=False, index=True) # index是建立普通索引 20 ctime = Column(DateTime, default=datetime.datetime.now) # 这里我们不能加(),在编译的过程中会自动加上, 21 # 如果我们在这里加上之后就会以程序启动的时间为当前时间,并且固定在这里了,不会自动切换了 22 lesson_id = Column(Integer, ForeignKey('class.id')) # 外键关联的字段用表名.字段名的格式 23 sc = relationship('Classes', backref='stcs') 24 25 26 class Hobby(Bar): 27 __tablename__ = 'hobby' 28 id = Column(Integer, primary_key=True, autoincrement=True) 29 title = Column(String(20), default='sing the song') 30 31 32 class Stuent2Hobby(Bar): 33 __tablename__ = 'sts2ho' 34 id = Column(Integer, primary_key=True, autoincrement=True) 35 student_id = Column(Integer, ForeignKey('student.id')) 36 hobby_id = Column(Integer, ForeignKey('hobby.id')) 37 38 __table_args__ = ( 39 UniqueConstraint('student_id', 'hobby_id', name='uix_student_id_hobby_id'), 40 ) # 这里是创建联合唯一索引,就相当于我们的mysql里面的index('ix_id_name','name','extra'), 41 42 43 class Person(Bar): 44 __tablename__='person' 45 id=Column(Integer,primary_key=True,autoincrement=True) 46 age=Column(Integer) 47 name=Column(String(20),nullable=True) 48 49 def init_a(): 50 xxx = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 51 Bar.metadata.create_all(xxx) 52 53 54 def drop_b(): 55 aaa = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 56 Bar.metadata.drop_all(aaa) 57 58 59 if __name__ == '__main__': 60 init_a() 61 # drop_b()

1 from sqlalchemy.ext.declarative import declarative_base 2 from sqlalchemy import Column, Integer, String 3 from sqlalchemy import create_engine 4 5 Model_Base = declarative_base() 6 7 8 # 创建表单 9 class Users(Model_Base): 10 __tablename__ = 'usertable' 11 id = Column(Integer, primary_key=True, autoincrement=True) 12 name = Column(String(20)) 13 pwd = Column(String(14)) 14 __table_args__ = { 15 'mysql_charset': 'utf8', 16 'mysql_engine': 'InnoDB', 17 } 18 19 20 def init_db(): 21 engine = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 22 Model_Base.metadata.create_all(engine) 23 24 25 def drop_db(): 26 engine = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 27 Model_Base.metadata.drop_all(engine) 28 29 30 if __name__ == '__main__': 31 init_db() 32 # drop_db() # 创建关联表的时候,不能这样直接用我们的drop_all去删除,有坑,会报错 33 # 还有我们在这里执行完表格的创建和删除之后要到我们的mysql数据库里面去查询结果

1 from sqlalchemy import create_engine 2 engine=create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 3 obj=engine.execute('select name from loginuser') 4 result=obj.fetchall() 5 print(result) # [('peter',), ('eval',)] 连接成功

1 from sqlalchemy_demo.sqlalchemy.models import Users 2 from sqlalchemy import create_engine 3 from sqlalchemy.orm import sessionmaker 4 engine=create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8') 5 www=sessionmaker(bind=engine) 6 session=www() 7 8 oh=Users(name='peter',pwd='213') 9 ow=Users(name='wusir',pwd=123) 10 session.add(oh) 11 session.add(ow) 12 session.commit()

1 from sqlalchemy_demo.sqlalchemy import model 2 from sqlalchemy.orm import sessionmaker 3 from sqlalchemy import create_engine,text 4 from sqlalchemy.sql import func 5 connect=create_engine("mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8") 6 ses=sessionmaker(bind=connect) 7 session=ses() 8 9 # 添加多条数据 10 # obj=[ 11 # model.Classes(cname='python2period'), 12 # model.Classes(cname='python1period'), 13 # model.Classes(cname='python3period') 14 # ] 15 # session.add_all(obj) 16 # session.commit() 17 18 # 查询 19 # ret=session.query(model.Classes).all() 20 # for i in ret: 21 # print(i.id,i.cname) 22 23 # 删除 24 # session.query(model.Classes).filter(model.Classes.id>15).delete() 25 # session.commit() 26 27 # change/update 28 # session.query(model.Classes).filter(model.Classes.cname=='web').update({model.Classes.cname:'web_flask'}) # 直接赋值的方法修改 29 # session.query(model.Person).filter(model.Person.id>0).update({'age':model.Person.age-20},synchronize_session='evaluate') 30 # 这里我们的参数里面设置的synchronize_session='evaluate' 得到的是数字之间的运算结果,我们如果要修改数据库中的数字类型的话 31 32 # session.query(model.Classes).filter(model.Classes.id>5).update({'cname':model.Classes.cname+'hello'},synchronize_session=False) 33 # 这个参数的值设置为False,我们就得到的是字符串的拼接, 34 35 # 关联查询 36 ret=session.query(model.Classes).filter(model.Classes.id.in_(session.query(model.Classes.id).filter_by(cname='javahello'))).all() 37 obj=session.query(model.Classes).from_statement(text("SELECT * FROM class where cname=:name")).params(name='javahello').first() 38 # print(obj) 39 40 rea=session.query(func.count(model.Classes.id).label('cid')).filter(model.Student.id==model.Classes.id).correlate(model.Classes).as_scalar() 41 result=session.query(model.Classes.cname,rea) 42 print(result) 43 """ 44 得到的result是sql语句,细细体会吧. 45 46 SELECT class.cname AS class_cname, (SELECT count(class.id) AS cid 47 FROM student 48 WHERE student.id = class.id) AS anon_1 49 FROM class 50 """ 51 52 session.commit() 53 session.close()
=======================================================================================================================================

1 """ 2 这里是源码里面的逻辑代码 3 4 session = scoped_session对象 { 5 session_factory = XXXXXX, 6 registry = ThreadLocalRegistry{ 7 createfunc=XXXXXX, 8 registry=threading.local() 9 } 10 } 11 12 class scoped_session: 13 def add(self, *args, **kwargs): 14 return getattr(self.registry(), 'add')(*args, **kwargs) 15 16 def add_all(self, *args, **kwargs): 17 return getattr(self.registry(), 'add_all')(*args, **kwargs) 18 19 def commit(self, *args, **kwargs): 20 return getattr(self.registry(), 'commit')(*args, **kwargs) 21 22 def query(self, *args, **kwargs): 23 return getattr(self.registry(), 'query')(*args, **kwargs) 24 """ 25 26 27 from sqlalchemy_demo.sqlalchemy.model import * 28 from threading import Thread 29 from sqlalchemy.orm import sessionmaker,scoped_session 30 from sqlalchemy import create_engine 31 32 engine = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8', pool_size=3, max_overflow=0) 33 qqx = sessionmaker(bind=engine) 34 sess = scoped_session(qqx) 35 36 """ 37 我们的sessionmaker实例化出来的对象在这里可以自定义,然后我们就用这个自定义的对象去数据库获取数据对象 38 """ 39 40 41 def whh(): 42 data = sess.query(Classes).filter(Classes.id>14).first() 43 # for i in data: 44 # print(i.id, i.cname) 45 print(data, type(data)) 46 sess.remove() 47 48 49 for i in range(5): 50 a = Thread(target=whh) 51 a.start()

1 from sqlalchemy_demo.sqlalchemy.model import * 2 from threading import Thread 3 from sqlalchemy.orm import sessionmaker 4 from sqlalchemy import create_engine 5 6 engine = create_engine('mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8', pool_size=3, max_overflow=0) 7 qqx = sessionmaker(bind=engine) 8 sess = qqx() 9 10 """ 11 我们的sessionmaker实例化出来的对象在这里可以自定义,然后我们就用这个自定义的对象去数据库获取数据对象 12 """ 13 14 15 def whh(): 16 data = sess.query(Classes).all() 17 for i in data: 18 print(i.id, i.cname) 19 # print(data, type(data)) 20 sess.close() 21 22 23 for i in range(5): 24 a = Thread(target=whh) 25 a.start()