MySQL—ORM框架,sqlalchemy模塊

武老師博客:ORM框架介紹html

 

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,而後在數據庫建立表 mysql

  - DB first: 手動建立數據庫以及表 -> ORM框架 -> 自動生成類
  - code first: 手動建立類、和數據庫 -> ORM框架 -> 以及表 SQLAlchemy 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()

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:gkx321@127.0.0.1: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:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
    Base.metadata.drop_all(engine)  #刪除類對應的全部表

engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1: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:gkx321@127.0.0.1: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 就能夠獲取表格整行數據session

# 誰有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:gkx321@127.0.0.1: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
相關文章
相關標籤/搜索