1. 程式人生 > >MySQL—ORM框架,sqlalchemy模塊

MySQL—ORM框架,sqlalchemy模塊

alex href 條件 upd 初識 有道 pytho imp list

武老師博客: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,想有,要裝第三方工具
#作用 #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:pass@host:port/dbname[?key=value&key=value...] 更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html ‘‘‘
ORM框架初識

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

MySQL—ORM框架,sqlalchemy模塊