import datetime from sqlalchemy import create_engine from sqlalchemy.orm import declarative_base, relationship from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index Base = declarative_base() # Base 當成 models.Model ### 單表 class User(Base): __tablename__ = 'users' # 表名 # 寫欄位 id = Column(Integer, primary_key=True, autoincrement=True) # id 主鍵 name = Column(String(32), index=True, nullable=False) # name列,索引,不可為空 email = Column(String(32), unique=True) # datetime.datetime.now不能加括號,加了括號,以後永遠是當前時間 ctime = Column(DateTime, default=datetime.datetime.now) extra = Column(Text) def __str__(self): return self.name def __repr__(self): return self.name # 一對多 :一個興趣被多個人喜歡 一個人只喜歡一個興趣 class Hobby(Base): __tablename__ = 'hobby' id = Column(Integer, primary_key=True) caption = Column(String(50), default='籃球') def __str__(self): return self.caption def __repr__(self): return self.caption class Person(Base): __tablename__ = 'person' id = Column(Integer, primary_key=True) name = Column(String(32), index=True, nullable=True) # hobby指的是tablename而不是類名,uselist=False # 外來鍵關聯--》強外來鍵--》物理外來鍵 hobby_id = Column(Integer, ForeignKey("hobby.id")) # 跟資料庫無關,不會新增欄位,只用於快速連表操作 # 類名,backref用於反向查詢 hobby = relationship('Hobby', backref='pers') def __str__(self): return self.name def __repr__(self): return self.name
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from models import Hobby, Person, User engine = create_engine( "mysql+pymysql://root:1234@127.0.0.1:3306/sqlalchemy02", max_overflow=0, # 超過連線池大小外最多建立的連線 pool_size=5, # 連線池大小 pool_timeout=30, # 池中沒有執行緒最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對執行緒池中的執行緒進行一次連線的回收(重置) ) Session = sessionmaker(bind=engine) session = Session() # 1 增加 Hobby # hobby = Hobby(caption='足球') # hobby1 = Hobby() # session.add_all([hobby, hobby1]) # session.commit() # 2 增加Person # p1 = Person(name='彭于晏', hobby_id=1) # p2 = Person(name='劉亦菲', hobby_id=2) # session.add_all([p1, p2]) # session.commit() # 3 簡便方式增加person---》增加Person,直接新增Hobby # hobby1 = Hobby(caption='乒乓球') # p1 = Person(name='彭于晏', hobby=hobby1) # 前提是必須有relationship # session.add(p1) # session.commit() # # 4 基於物件的跨表查詢---正向 # per=session.query(Person).filter_by(name='彭于晏').first() # print(per) # # 正向 # print(per.hobby.caption) # 5 基於物件的跨表查詢---正向 hobby=session.query(Hobby).filter_by(caption='籃球').first() print(hobby) # 反向--->拿到多條 print(hobby.pers) print(hobby.pers[0].name) # 列表套物件
import datetime from sqlalchemy import create_engine from sqlalchemy.orm import declarative_base, relationship from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index Base = declarative_base() # Base 當成 models.Model ### 單表 class User(Base): __tablename__ = 'users' # 表名 # 寫欄位 id = Column(Integer, primary_key=True, autoincrement=True) # id 主鍵 name = Column(String(32), index=True, nullable=False) # name列,索引,不可為空 email = Column(String(32), unique=True) # datetime.datetime.now不能加括號,加了括號,以後永遠是當前時間 ctime = Column(DateTime, default=datetime.datetime.now) extra = Column(Text) def __str__(self): return self.name def __repr__(self): return self.name # 一對多 :一個興趣被多個人喜歡 一個人只喜歡一個興趣 class Hobby(Base): __tablename__ = 'hobby' id = Column(Integer, primary_key=True) caption = Column(String(50), default='籃球') def __str__(self): return self.caption def __repr__(self): return self.caption class Person(Base): __tablename__ = 'person' id = Column(Integer, primary_key=True) name = Column(String(32), index=True, nullable=True) # hobby指的是tablename而不是類名,uselist=False # 外來鍵關聯--》強外來鍵--》物理外來鍵 hobby_id = Column(Integer, ForeignKey("hobby.id")) # 跟資料庫無關,不會新增欄位,只用於快速連表操作 # 類名,backref用於反向查詢 hobby = relationship('Hobby', backref='pers') def __str__(self): return self.name def __repr__(self): return self.name # 多對多 class Boy2Girl(Base): __tablename__ = 'boy2girl' id = Column(Integer, primary_key=True, autoincrement=True) girl_id = Column(Integer, ForeignKey('girl.id')) boy_id = Column(Integer, ForeignKey('boy.id')) # boy = relationship('Boy', backref='boy') class Girl(Base): __tablename__ = 'girl' id = Column(Integer, primary_key=True) name = Column(String(64), unique=True, nullable=False) class Boy(Base): __tablename__ = 'boy' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(64), unique=True, nullable=False) # 與生成表結構無關,僅用於查詢方便,放在哪個單表中都可以--等同於manytomany girls = relationship('Girl', secondary='boy2girl', backref='boys') if __name__ == '__main__': # 3.1 建立引擎 engine = create_engine( "mysql+pymysql://root:1234@127.0.0.1:3306/sqlalchemy02", max_overflow=0, # 超過連線池大小外最多建立的連線 pool_size=5, # 連線池大小 pool_timeout=30, # 池中沒有執行緒最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對執行緒池中的執行緒進行一次連線的回收(重置) ) ## 3.2 把表模型同步到資料庫中 Base.metadata.create_all(engine) # 3.3 刪除表 # Base.metadata.drop_all(engine)
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from models import Hobby, Person, User, Boy, Girl, Boy2Girl engine = create_engine( "mysql+pymysql://root:1234@127.0.0.1:3306/sqlalchemy02", max_overflow=0, # 超過連線池大小外最多建立的連線 pool_size=5, # 連線池大小 pool_timeout=30, # 池中沒有執行緒最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對執行緒池中的執行緒進行一次連線的回收(重置) ) Session = sessionmaker(bind=engine) session = Session() # 1 增加 Boy # boy = Boy(name='王小剛') # boy2 = Boy(name='王小明') # boy3 = Boy(name='王小勇') # session.add_all([boy,boy2,boy3]) # session.commit() # 2 增加Girl # girl = Girl(name='張小華') # girl2 = Girl(name='劉小紅') # girl3 = Girl(name='李小麗') # session.add_all([girl3, girl2, girl]) # session.commit() # 3 增加Boy2Girl # obj1=Boy2Girl(boy_id=1,girl_id=1) # obj2=Boy2Girl(boy_id=1,girl_id=2) # obj3=Boy2Girl(boy_id=1,girl_id=3) # session.add_all([obj2, obj3, obj1]) # session.commit() # ------ # 3 簡便方式增加 # obj2=Girl(name='張亦菲') # obj3=Girl(name='李娜扎') # obj1=Boy(name='張小勇',girls=[obj2,obj3]) # # session.add(obj1) # session.commit() # # 4 基於物件的跨表查詢---正向 # boy=session.query(Boy).filter_by(name='張小勇').first() # print(boy.girls[0].name) # 5 基於物件的跨表查詢---反向 girl=session.query(Girl).filter_by(name='張亦菲').first() print(girl.boys)
# session 物件,整合到flask中去,要把session物件做成全域性(大家公用),還是每個檢視函式獨有一個(每次都要例項化得到這個session物件) # 每個檢視函式獨有一個---》每次都要例項化---》sqlalchemy提供了一種方式,讓咱們使用全域性的一個session,但是每個檢視函式中使用的都是不同的 request,session都是這種實現機制 # sqlalchemy提供了一種,在不同執行緒中,雖然使用全域性 session,實際上每個執行緒自己獨有一個session
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session from models import Users from threading import local engine = create_engine("mysql+pymysql://root:lqz123?@127.0.0.1:3306/sqlalchemy01", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) """ # 執行緒安全,基於本地執行緒實現每個執行緒用同一個session # 特殊的:scoped_session中有原來方法的Session中的一下方法: public_methods = ( '__contains__', '__iter__', 'add', 'add_all', 'begin', 'begin_nested', 'close', 'commit', 'connection', 'delete', 'execute', 'expire', 'expire_all', 'expunge', 'expunge_all', 'flush', 'get_bind', 'is_modified', 'bulk_save_objects', 'bulk_insert_mappings', 'bulk_update_mappings', 'merge', 'query', 'refresh', 'rollback', 'scalar' ) """ # session=Session() # 不是執行緒安全---》多執行緒併發情況下---》用的是同一個,就會出現混亂 #scoped_session類並沒有繼承Session,但是卻又它的所有方法 # 以後在多執行緒,協程情況下,使用這個session,就沒有併發安全的問題 # 原理是什麼? 內部使用了threading包下local物件, local.session 在不同執行緒下執行這個取值或賦值,使用的都是當前執行緒自己的 # 執行緒1 local.a=100 後續的操作中--->取local.a--->永遠是當時這條執行緒中放進去的a ,也就是100 # 執行緒2 local.a=999 --->取local.a--->永遠是當時這條執行緒中放進去的a ,也就是999 #local物件如何實現的執行緒安全呢? 內部維護了一個字典,字典的key是執行緒id號,value值是 # l=local() # {} # # 執行緒1 # l.session=執行緒1的session # {執行緒1的id號:{session:新session}} # # # 執行緒2 # l.session# {執行緒1的id號:{session:新session},執行緒2的id號:{session:執行緒2的session}} # 本質就是,不同執行緒,使用自己執行緒的那個session # scoped_session 不是Session類的物件,但是他有 Session類物件的所有方法----》透過裝飾器,裝進去的 session = scoped_session(Session) # ############# 執行ORM操作 ############# obj1 = Users(name="lqz4",email='3533@qq.com') session.add(obj1) # 提交事務 session.commit() # 關閉session session.close()
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session from models import User, Person, Hobby, Boy, Girl, Boy2Girl from sqlalchemy.sql import text engine = create_engine("mysql+pymysql://root:1234@127.0.0.1:3306/sqlalchemy02", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) session = scoped_session(Session) # 1 新增, add add_all # 2 刪除 # 2.1 session.query(Users).filter_by(id=1).delete() # 2.1 session.delete(物件) # user = session.query(User).filter_by(id=1).first() # session.delete(user) # session.commit() # 修改 # 1 方式一: # session.query(Boy).filter_by(id=1).update({'name':'lqz'}) # session.commit() # # 2 方式二 類名.屬性名,作為要修改的key # session.query(Boy).filter_by(id=4).update({Boy.name:'lqz1'}) # session.commit() # # id為4的人的名字後+ _nb 類似於django的 F 查詢 # session.query(User).filter_by(id=2).update({'name':User.name+'_nb'},synchronize_session=False) # 字串拼接 # session.query(User).filter_by(id=2).update({'id':User.id+6}, synchronize_session="evaluate") # 數字之間加 # session.commit() # # 3 方式三: # 物件.name='xxx' #session.add(物件) # boy=session.query(Boy).filter_by(id=1).first() # boy.name='xxzzyy' # session.add(boy) # 有id就是修改,沒有就是新增 # session.commit() ### 4 查詢---》基本查詢 # 4.1 filter_by 寫條件 # res=session.query(User).filter_by(name='lqz_nb',id=8).first() # res=session.query(User).filter_by(name='lqz').all() # 放在列表中 不是queryset物件 # 4.2 filter 寫表示式 # res=session.query(User).filter(User.name=='lqz_nb').first() # res=session.query(User).filter(User.id>=3).all() # res=session.query(User).filter(User.name!='lqz').all() # 4.3 只查表中某幾個欄位,並重新命名 # select name as xx,age from user; # res=session.query(User.name.label('xx'), User.email) # select name,email from user; # res=session.query(User.name, User.email).all() # res=session.query(User) # 4.4 條件可以使用text自己拼湊 # select * from user where id< 224 and name=lqz order by id # res = session.query(User).filter(text("id<:value and name=:name")).params(value=224, name='lqz_nb').order_by(User.id).all() # print(res) ## 4.5 直接原生sql # SELECT * FROM users where name=lqz # res = session.query(User).from_statement(text("SELECT * FROM users where name=:name")).params(name='lqz_nb').all() res = session.query(User).from_statement(text("SELECT * FROM users where name=:name")).params(name='張三') print(res)