ORM介紹html
orm英文全稱object relational mapping,就是對象映射關係程序,簡單來講咱們相似python這種面向對象的程序來講一切皆對象,可是咱們使用的數據庫卻都是關係型的,爲了保證一致的使用習慣,經過orm將編程語言的對象模型和數據庫的關係模型創建映射關係,這樣咱們在使用編程語言對數據庫進行操做的時候能夠直接使用編程語言的對象模型進行操做就能夠了,而不用直接使用sql語言。python
orm的優勢:mysql
缺點:程序員
SQLAlchemy是Python編程語言下的一款ORM框架,該框架創建在數據庫API之上,使用關係對象映射進行數據庫操做,簡言之即是:將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果sql
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:password@host:port/dbname[?key=value&key=value...] 更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html
ORM建立表結構:編程
方法1:session
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String # create_engine() 初始化數據庫鏈接 # '數據庫類型+數據庫驅動名稱://用戶名:口令@機器地址:端口號/數據庫名' # charset=utf-8 設置表支持中文字符、echo=True打印建立過程 engine = create_engine("mysql+pymysql://root:123456@localhost/oldboy?charset=utf-8", encoding="utf-8",echo=True) Base = declarative_base() # 建立orm的基類 # 定義User對象 class User(Base): __tablename__ = "user" # 表的名字 # 表的結構 id = Column(Integer,primary_key=True) name = Column(String(32)) password = Column(String(64)) Base.metadata.create_all(engine) # 建立表結構
方法二:數據結構
from sqlalchemy import Table,MetaData,Column,Integer,String,create_engine from sqlalchemy.orm import mapper engine = create_engine("mysql+pymysql://root:123456@localhost/oldboy?charset=utf8",echo=True) metadata = MetaData() user = Table("user",metadata, Column("id",Integer,primary_key=True), Column("name",String(50)), Column("fullname",String(50)), Column("password",String(12)) ) class User(object): def __init__(self,name,fullname,password): self.name = name self.fullname = fullname self.password = password mapper(User,user) # 建立映射關係 metadata.create_all(engine) # 建立表結構
插入數據:oracle
Session_class = sessionmaker(bind=engine) # 建立與數據庫的會話session class,返回的是個class,不是實例 Session = Session_class() # 生成session實例 user_obj = User(name="alex",password="alex3714") # 生成要建立的數據對象 print(user_obj.name,user_obj.id) # 此時還沒建立對象,user_obj.id返回None Session.add(user_obj) # 把要建立的數據對象添加到session裏,統一建立 print(user_obj.name,user_obj.id) # 此時也依然沒建立 Session.commit() # 統一提交,建立數據
查詢數據:
# query:查詢對象、filter_by:過濾條件、first:顯示第一個
my_user = Session.query(User).filter_by(name="alex").first() print(my_user) # 返回的是內存地址<__main__.User object at 0x7f92d89ef518> 在User類中加入__repr__函數,可將內存地址中相應數據返回 # 重構__repr__方法後,無論直接輸出對象仍是經過print打印的信息都按咱們__repr__方法中定義的格式進行顯示
def __repr__(self): # __repr__ 和 __str__這兩個方法都是用於顯示的,__str__是面向用戶的,而__repr__面向程序員
return "<%s(name=%s,password=%s)>" %(self.__class__.name,self.name,self.password)
修改數據:
my_user = Session.query(User).filter_by(name="alex").filter_by(password="sb1234").first() # 多個條件時可加多個filter_by my_user.name="Alex Li" # 修改mysql_user中name的值 Session.commit() # 提交
事務回滾:
my_user = Session.query(User).filter_by(id=1).first() # 查id=1的數據 my_user.name = "Jack" # 修改id=1數據中的name fake_user = User(name="Rain",password="123456") # 插入數據 Session.add(fake_user) # 要插入的數據添加到Session裏面 # filter與filter_by都是過濾條件,用法相似,裏面的條件語句不一樣 print(Session.query(User).filter(User.name.in_(["Jack","rain"])).all()) # 查詢出全部User對象中name爲Jack、rain的 Session.rollback() # 事務回滾 print(Session.query(User).filter(User.name.in_(["Jack","rain"])).all())
簡單語句:
# all()獲取全部數據 Session.query(User.name,User.id).all() # 多條件查詢 Session.query(User).filter(User.id>1).filter(User.id<7).all() # 統計次數 Session.query(User).filter(User.name.like("Ra%")).count() # 分組 from sqlalchemy import func Session.query(User.name,func.count(User.name)).group_by(User.name).all() # 按User.name分組 至關於sql: select user.name,count(user.name) from user group by user.name;
外鍵關聯:
from sqlalchemy import ForeignKey,Column,String,Integer from sqlalchemy.orm import relationship,sessionmaker from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:123456@localhost/oldboy?charset=utf8", encoding="utf8") Base = declarative_base() # 建立ORM基類 session_class = sessionmaker(bind=engine) # 對錶的操做交給session_class來操做,返回的是一個class session = session_class() # 建立一個session對象,在session中完成多個事務 class User(Base): __tablename__ = "user" id = Column(Integer,primary_key=True) name = Column(String(32)) password = Column(String(64)) def __repr__(self): return "<User(name=%s,password=%s)>" %(self.name,self.password) class Address(Base): __tablename__ = "addresses" id = Column(Integer,primary_key=True) email_address = Column(String(32),nullable=False) #注意點:增長用戶時user_id只能是表user中存在的id,不然會報錯 user_id = Column(Integer,ForeignKey("user.id")) # addresses表中的外鍵關聯user表中的id # relationship函數是sqlalchemy對關係之間提供的一種便利的調用方式 user = relationship("User",backref="addresses") # 經過user調用user表中的變量, user表中經過addresses調用addresses表中的變量 def __repr__(self): return "<Address(email_address=%s)>" %self.email_address Base.metadata.create_all(engine) # 構造表結構 obj = session.query(User).all()[0] # 查詢user表語句 print("obj.addresses:",obj.addresses) obj.addresses = [Address(email_address="r1@126.com"), Address(email_address="r2@126.com")] # 經過user對象反查關聯的addresses插入數據
for i in obj.addresses: # 經過user對象反查關聯的addresses記錄
print(i)
session.commit() # 事務提交 addr_obj = session.query(Address).all()[-1] # 查看address表中的數據 print(addr_obj.user) # 經過user查看user表中的數據
經常使用 查詢語法:
equals: query.filter(User.name == "ed") not equals: query.filter(User.name != "ed") like: query.filter(User.name.like("%ed%")) in: query.filter(User.name.in_(["ed","wendy","jack"])) not in: query.filter(~User.name.in_(["ed","wendy","jack"])) is null / is not null: query.filter(User.name == None) query.filter(User.name.is_(None)) query.filter(User.name != None) query.filter(User.name.isnot(None)) and: from sqlalchemy import and_ query.filter(and_(User.name == "ed",User.fullname == "Ed Jones")) query.filter(User.name == "ed",User.fullname == "Ed Jones") query.filter(User.name == "ed").filter(User.fullname == "Ed Jones") or: from sqlalchemy import or_ query.filter(or_(User.name == "ed",User.fullname == "Ed Jones")) match: query.filter(User.name.match("wendy"))
多外鍵關聯:(Customer表有2個字段都關聯了Address表)
1 from sqlalchemy import Integer,ForeignKey,String,Column 2 from sqlalchemy.ext.declarative import declarative_base 3 from sqlalchemy.orm import relationship 4 from sqlalchemy import create_engine 5 6 engine = create_engine("mysql+pymysql://root:123456@localhost/oldboy?charset=utf8") 7 8 Base = declarative_base() 9 10 11 class Customer(Base): 12 __tablename__ = "customer" 13 id = Column(Integer,primary_key=True) 14 name = Column(String(32)) 15 16 billing_address_id = Column(Integer,ForeignKey("address.id")) 17 shopping_address_id = Column(Integer,ForeignKey("address.id")) 18 19 bill_address = relationship("Address",foregin_keys=[billing_address_id]) 20 shopping_address = relationship("Address",foregin_keys=[shopping_address_id]) 21 22 23 class Address(Base): 24 __tablename__ = "address" 25 id = Column(Integer,primary_key=True) 26 street = Column(String(32)) 27 city = Column(String(32)) 28 state = Column(String(32)) 29 30 31 Base.metadata.create_all(engine)
多對多關係:
1 from sqlalchemy import Table,Column,Integer,String,DATE,ForeignKey 2 from sqlalchemy.orm import relationship 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import create_engine 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:123456@localhost/oldboy?charset=utf8", 8 encoding="utf8") 9 10 Base = declarative_base() 11 12 # 外鍵關聯表,ORM自動維護,不須要手動維護的通常採用Table這種方式建立 13 book_m2m_author = Table("book_m2m_author",Base.metadata, 14 Column("book_id",Integer,ForeignKey("books.id")), 15 Column("author_id",Integer,ForeignKey("authors.id")) 16 ) 17 18 class Book(Base): 19 __tablename__ = "books" 20 id = Column(Integer,primary_key=True) 21 name = Column(String(32)) 22 pub_date = Column(DATE) 23 authors = relationship("Author",secondary=book_m2m_author,backref="books") 24 25 def __repr__(self): 26 return self.name 27 28 29 class Author(Base): 30 __tablename__ = "authors" 31 id = Column(Integer,primary_key=True) 32 name = Column(String(32)) 33 34 def __repr__(self): 35 return self.name 36 37 Base.metadata.create_all(engine) 38 39 40 session_class = sessionmaker(bind=engine) 41 s = session_class() 42 43 b1 = Book(name="Python自動化") 44 b2 = Book(name="人工智能") 45 b3 = Book(name="心靈雞湯") 46 b4 = Book(name="讀者") 47 48 a1 = Author(name="Alex") 49 a2 = Author(name="Jack") 50 a3 = Author(name="Rain") 51 52 b1.authors = [a1,a2] 53 b2.authors = [a1,a2,a3] 54 55 s.add_all([b1,b2,b3,a1,a2,a3]) 56 57 s.commit() 58 59 # ------------ 書名查做者 ---------------- 60 obj = s.query(Book).filter(Book.name.like("%ython%")).first() 61 print(obj.name,obj.authors) 62 63 # ------------ 做者查書名 ---------------- 64 author_obj = s.query(Author).filter_by(name="Alex").first() 65 print(author_obj.name,author_obj.books)
刪除數據時不用管boo_m2m_authors , sqlalchemy會自動幫你把對應的數據刪除
經過書刪除做者
刪除數據時不用管boo_m2m_authors , sqlalchemy會自動幫你把對應的數據刪除 經過書刪除做者 author_obj =s.query(Author).filter_by(name="Jack").first() book_obj = s.query(Book).filter_by(name="跟Alex學把妹").first() book_obj.authors.remove(author_obj) #從一本書裏刪除一個做者 s.commit()
直接刪除做者
刪除做者時,會把這個做者跟全部書的關聯關係數據也自動刪除
author_obj =s.query(Author).filter_by(name="Alex").first() # print(author_obj.name , author_obj.books) s.delete(author_obj) s.commit()
處理中文
sqlalchemy設置編碼字符集必定要在數據庫訪問的URL上增長charset=utf8,不然數據庫的鏈接就不是utf8的編碼格式
eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
補充知識點: