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

MySQL—ORM框架,sqlalchemy模組

武老師部落格: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:[email protected]: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