MySQL—ORM框架,sqlalchemy模組
阿新 • • 發佈:2018-11-09
武老師部落格:ORM框架介紹
import os #1.當一類函式公用同樣引數時候,可以轉變成類執行 - 分類 #2.面向物件: 資料和邏輯組合在一起了 #3. 一類事物共同用有的屬性和行為(方法) #因此 表其實可以寫成一個類 #雙下方法item 和 call 必須要背會: class Userinfo: def __init__(self,id,name): self.id = id self.name = name def show(self): print面向物件複習('in the show') def __call__(self, *args, **kwargs): print('你在呼叫call雙下方法哦') def __getitem__(self, item): return self.__dict__[item] def __setitem__(self,key,value): self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] user1 = Userinfo(1,'gkx') #類似表第一行 user1() user1['age'] = 22 print(user1.__dict__) print(user1['id']) # del user1['age'] #呼叫 __delitem__ 方法 del user1.age #原生方法 print(user1.__dict__)
#ORM : object relational mapper #1.ORM框架: ORM-->關係物件對映 : SQLAlchemy:code first,預設沒有db first,想有,要裝第三方工具ORM框架初識#作用 #1.提供簡單的規則 #2.自動轉換成sql語句 #兩類 # DB first / code first 所有的ORM都是建立一個類,讓類去對應表 ''' DB first: 幫你從db中把已建立好的表,連上db後,自動把錶轉化為程式碼中的一個個類 Code first: 先有類和db,然後在資料庫建立表 - DB first: 手動建立資料庫以及表 -> ORM框架 -> 自動生成類 - code first: 手動建立類、和資料庫 -> ORM框架 -> 以及表 SQLAlchemy ''' #20181011 ORM框架 圖在有道詞典 #SQLAlchemy 不進行連線,要用pymysql等進行連線 ''' SQLAlchemy是Python程式語言下的一款ORM框架,該框架建立在資料庫API之上,使用關係物件對映進行資料庫操作, 簡言之便是:將物件轉換成SQL,然後使用資料API執行SQL並獲取執行結果。 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:[email protected]:port/dbname[?key=value&key=value...] 更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html '''
sqlalchemy是codefirst
DB first: 幫你從db中把已建立好的表,連上db後,自動把錶轉化為程式碼中的一個個類
Code first: 先有類和db,然後在資料庫建立表
- DB first: 手動建立資料庫以及表 -> ORM框架 -> 自動生成類
- code first: 手動建立類、和資料庫 -> ORM框架 -> 以及表 SQLAlchemy
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 Base = declarative_base() class UserType(Base): __tablename__ = 'usertype' id = Column(Integer,primary_key=True,autoincrement=True) title = Column(String(32),nullable=True,index=True) class Users(Base): __tablename__ = 'users' id = Column(Integer,primary_key=True,autoincrement=True) name = Column(String(32),nullable=True,index=True) email = Column(String(16),unique=True) user_type_id = Column(Integer,ForeignKey("usertype.id")) # __table_args__ = ( # UniqueConstraint('id','name',name='uix_id_name'), # Index('ix_n_ex','name','email') # ) def create_db(): engine = create_engine("mysql+pymysql://root:[email protected]:3306/ORMdb?charset=utf8", max_overflow=5) Base.metadata.create_all(engine) # Base.metadata.drop_all(engine) #刪除類對應的所有表 def drop_db(): engine = create_engine("mysql+pymysql://root:[email protected]:3306/ORMdb?charset=utf8", max_overflow=5) Base.metadata.drop_all(engine) #刪除類對應的所有表 engine = create_engine("mysql+pymysql://root:[email protected]:3306/ORMdb?charset=utf8", max_overflow=5) Session = sessionmaker(bind=engine) session = Session() #類似pymysql中conn和cursor的綜合 #****增加**************** # obj1 = UserType(title='普通使用者') # session.add(obj1) # objs = [ # UserType(title='白銀使用者'), # UserType(title='黃金使用者') # ] # session.add_all(objs) #****查詢**************** ''' usertype_lst = session.query(UserType).all() print(session.query(UserType)) #----->> SELECT usertype.id AS usertype_id, usertype.title AS usertype_title FROM usertype print(usertype_lst) #一個列表,包含了usertype類中的每一個物件,而這每一個物件就對應usertype表的一行資料 for i in usertype_lst: print(i.id,i.title)#直接列印i會是一個物件的記憶體地址,應該這麼列印才有值 # ···usertype_lst = session.query(UserType.id).all() #如果query裡面不是一個類,而是一個屬性,那麼 usertype_lst是有值的,可以直接列印 ''' # usertype_lst = session.query(UserType.id,UserType.title).filter(UserType.id > 2) #或者 UserType.id ==2 # for i in usertype_lst: # print(i.title) #****刪除**************** # session.query(UserType.id,UserType.title).filter(UserType.id > 2).delete() #****修改**************** # session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({'title':'黑金'}) # session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({UserType.title:UserType.title + 'x'},synchronize_session=False) # session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({'title':UserType.title + 1},synchronize_session="evaluate") session.commit() session.close()用sqlalchemy建立類,及增刪該查
query: 類似select
filter:類似 where
【.】 : 類似sql裡的 空格 用來分割命令的
all : fetchone,fetchall,如果不加all,那麼列印ret就只是返回一句sql語句
#如果query裡是一個類,all的取值是一個個物件,如果query裡是一個 類.屬性 那麼ret可以直接打印出來
子查詢 select id,(select name from tb2 where id = xx) from tb2
#sqlalchemy 支援 分組,排序,連表,萬用字元,子查詢,limit,union,where
#如果語句很複雜,還支援 原生sql
#子查詢 select id,(select name from tb2 where id = xx) from tb2 #sqlalchemy 支援 分組,排序,連表,萬用字元,子查詢,limit,union,where #如果語句很複雜,還支援 原生sql 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 Base = declarative_base() engine = create_engine("mysql+pymysql://root:[email protected]:3306/ORMdb?charset=utf8", max_overflow=5) Session = sessionmaker(bind=engine) session = Session() #類似pymysql中conn和cursor的綜合 ''' # 條件 ret = session.query(Users).filter_by(name='alex').all() #filter_by內部呼叫的其實是filter,只是這裡用引數表示, filter Users.name='alex' 是表示式 ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all() #預設是and,除非宣告是or 見下方匯入 or_ 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() # 人家in_就是規定要這麼寫啊 ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all() # ~ 表示非 not in 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() #因為預設是and,此處不宣告 and_也可以的 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] # limit 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() # select * from Users,Favor where Users.id = Favor.nid #相當於inner join ret = session.query(Person).join(Favor).all() #如果兩個表有設定了foreign key ,那麼不用寫條件,自動關聯了 inner join ret = session.query(Person).join(Favor,isouter=True).all() #left join, right join呢? 表換一下位置就好了。。。 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() ''' #子查詢的正確寫法 : .subquery() .as_acalar() # 1. # select * from b where id in (select id from tb2) # 2 select * from (select * from tb) as B # q1 = session.query(UserType).filter(UserType.id > 0).subquery() # result = session.query(q1).all() # print(result) # 3 # select # id , # (select * from users where users.user_type_id=usertype.id) # from usertype; #第一次迴圈 拿到 id1 然後判斷id1與另一張表相等,拿到一個值 #第二次迴圈 拿到 id2 然後判斷id2與另一張表相等,拿到一個值... # session.query(UserType,session.query(Users).filter(Users.id == 1).subquery()) #錯誤寫法 # session.query(UserType,Users) #上面這麼寫,其實還是類似笛卡兒積,達不到子查詢的效果 # result = session.query(UserType.id,session.query(Users).as_scalar()) # print(result) # result = session.query(UserType.id,session.query(Users).filter(Users.user_type_id==UserType.id).as_scalar()) # print(result) session.commit() session.close()sqlalchemy—子查詢
通過設定relationship可以減少連錶帶來的冗餘程式碼,只要通過 obj.relationship_name 就可以獲取表格整行資料
# 誰有foreign key relationship就寫在哪裡 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 Base = declarative_base() engine = create_engine("mysql+pymysql://root:[email protected]:3306/ORMdb?charset=utf8", max_overflow=5) Session = sessionmaker(bind=engine) session = Session() #類似pymysql中conn和cursor的綜合 ''' 獲取使用者資訊以及與其關聯的使用者名稱稱: 用SQL的時候就是要先連表 ''' # 問題1. 獲取使用者資訊以及與其關聯的使用者型別名稱(FK,Relationship=>正向操作) # user_list = session.query(Users,UserType).join(UserType,isouter=True) # print(user_list) # for row in user_list: # print(row[0].id,row[0].name,row[0].email,row[0].user_type_id,row[1].title) # user_list = session.query(Users.name,UserType.title).join(UserType,isouter=True).all() # for row in user_list: # print(row[0],row[1],row.name,row.title) '''誰有foreign key relationship就寫在哪裡 relationalship~~~~ class Users(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(VARCHAR(32), nullable=True, index=True) email = Column(VARCHAR(16), unique=True) user_type_id = Column(Integer,ForeignKey("usertype.id")) user_type = relationship("UserType",backref='xxoo') ***********建立關係! 這個backref是給usertype用的,即父表用的 然後就可以使用以下方法來獲取了,不用連表這麼麻煩了''' # user_list = session.query(Users) # for row in user_list: # print(row.name,row.id,row.user_type.title) # 問題2. 獲取使用者型別 # type_list = session.query(UserType) 傳統方式 # for row in type_list: # print(row.id,row.title,session.query(Users).filter(Users.user_type_id == row.id).all()) # type_list = session.query(UserType) # for row in type_list: # print(row.id,row.title,row.xxoo) # 設定了backref後 # row.xxoo 就相當於 session.query(Users).filter(Users.user_type_id == row.id).all() """tb1 1 白金 2 黑金 obj.xx ==> [obj,obj...] #這叫做反向操作,設定了 backref='xx'後 """ """tb2 1 方少偉 1 2 成套 1 3 小白 2 # 正向 ut = relationship(backref='xx') obj.ut ==> 相當於拿到 tb1 在id對應位置一整行資料 這叫做正向操作 """ session.commit() session.close()ORM: relationship