Python開發【模塊】:sqlalchemy

1、對象映射關係(ORM)html

orm英文全稱object relational mapping,就是對象映射關係程序,簡單來講咱們相似python這種面向對象的程序來講一切皆對象,可是咱們使用的數據庫卻都是關係型的,爲了保證一致的使用習慣,經過orm將編程語言的對象模型和數據庫的關係模型創建映射關係,這樣咱們在使用編程語言對數據庫進行操做的時候能夠直接使用編程語言的對象模型進行操做就能夠了,而不用直接使用sql語言python

優勢:mysql

  • 隱藏了數據訪問細節,「封閉」的通用數據庫交互,ORM的核心。他使得咱們的通用數據庫交互變得簡單易行,而且徹底不用考慮該死的SQL語句。快速開發,由此而來
  • ORM使咱們構造固化數據結構變得簡單易行

缺點:linux

  • 無可避免的,自動化意味着映射和關聯管理,代價是犧牲性能(早期,這是全部不喜歡ORM人的共同點)。如今的各類ORM框架都在嘗試使用各類方法來減輕這塊(LazyLoad,Cache),效果仍是很顯著的

 

2、SQLAlchemy程序員

在Python中,最有名的ORM框架是SQLAlchemy。用戶包括openstack\Dropbox等知名公司或應用
sql

Dialect用於和數據API進行交流,根據配置文件的不一樣調用不一樣的數據庫API,從而實現對數據庫的操做,如:數據庫

MySQL-Python MySQLdb模塊
    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

注:支持鏈接MySQL、Oracles數據庫編程

安裝:windows

pip install SQLAlchemy
pip install pymysql  
#因爲mysqldb依然不支持py3,因此這裏咱們用pymysql與sqlalchemy交互

windows下python2.7環境MySQLdb模塊安裝session

官網http://www.codegood.com/downloads下載  MySQL-python-1.2.3.win32-py2.7.exe文件
下載完成後本地安裝
執行命令pip install MySQL-python完成,本地import MySQLdb

 

一、基本使用

查看mysql基礎知識移步-》》http://www.cnblogs.com/lianzhilei/p/5993282.html

下面就開始讓你見證orm的nb之處,盤古開天劈地以前,咱們建立一個表是這樣的:

CREATE TABLE user (
    id INTEGER NOT NULL AUTO_INCREMENT,
    name VARCHAR(32),
    password VARCHAR(64),
    PRIMARY KEY (id)
)

這只是最簡單的sql表,若是再加上外鍵關聯什麼的,通常程序員的腦容量是記不住那些sql語句的,因而有了orm,實現上面一樣的功能,代碼以下:

# 建立表結構

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import  declarative_base
from sqlalchemy import Column,Integer,String

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8",echo=True)      #echo=True 打印程序運行詳細信息

Base = declarative_base()   #生成orm基類

class User(Base):
    __tablename__ = "user"      #表名
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    password = Column(String(64))

Base.metadata.create_all(engine)    #建立表結構

# 打印輸出
# 2016-10-26 08:42:02,619 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
# 2016-10-26 08:42:02,619 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,622 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
# 2016-10-26 08:42:02,622 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,624 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
# 2016-10-26 08:42:02,624 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,649 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
# 2016-10-26 08:42:02,649 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,651 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
# 2016-10-26 08:42:02,651 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,652 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) 
# COLLATE utf8_bin AS anon_1
# 2016-10-26 08:42:02,652 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,655 INFO sqlalchemy.engine.base.Engine DESCRIBE `user`
# 2016-10-26 08:42:02,655 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,657 INFO sqlalchemy.engine.base.Engine ROLLBACK
# 2016-10-26 08:42:02,660 INFO sqlalchemy.engine.base.Engine
# CREATE TABLE user (
# 	id INTEGER NOT NULL AUTO_INCREMENT,
# 	name VARCHAR(32),
# 	password VARCHAR(64),
# 	PRIMARY KEY (id)
# )
#
#
# 2016-10-26 08:42:02,660 INFO sqlalchemy.engine.base.Engine {}
# 2016-10-26 08:42:02,904 INFO sqlalchemy.engine.base.Engine COMMIT

 查詢表結構:

mysql> desc user;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| name     | varchar(32) | YES  |     | NULL    |                |
| password | varchar(64) | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec) 

你說,娘那個腚的,並無感受代碼量變少啊,呵呵, 孩子莫猴急,好戲在後面

除上面的建立以外,還有一種建立表的方式,雖不經常使用,但仍是看看吧

from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
 
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) #the table metadata is created separately with the Table construct, then associated with the User class via the mapper() function
另外一種方式

 

二、建立數據

最基本的表咱們建立好了,那咱們開始用orm建立一條數據試試

# 建立表數據

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

class User(Base):
    __tablename__ = "user"      #表名
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    password = Column(String(64))

#Base.metadata.create_all(engine)    #建立表結構

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

user_obj = User(name="lzl",password="123456")   #生成你要建立的數據對象
print(user_obj.name,user_obj.id)  #此時還沒建立對象呢,不信你打印一下id發現仍是None

Session.add(user_obj) #把要建立的數據對象添加到這個session裏, 一會統一建立
print(user_obj.name,user_obj.id) #此時也依然還沒建立

Session.commit()    #現此才統一提交,建立數據

# lzl None
# lzl None

我擦,寫這麼多代碼才建立一條數據,你表示太tm的費勁了,正要轉身離開,我拉住你的手不放開,高潮快來了。。

 

三、查詢數據

# 查詢

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

class User(Base):
    __tablename__ = "user"      #表名
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    password = Column(String(64))

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

my_user = Session.query(User).filter_by(name="lzl").first()
print(my_user)          #my_user此時是一個對象
#<__main__.User object at 0x03EFC6D0>

print(my_user.id,my_user.name,my_user.password)
# 1 lzl 123456

不過剛纔上面的顯示的內存對象對址你是沒辦法分清返回的是什麼數據的,除非打印具體字段看一下,若是想讓它變的可讀,只需在定義表的類下面加上這樣的代碼:

def __repr__(self):
  return "<User(name='%s',  password='%s')>" % (
  self.name, self.password)

print(my_user)
#<User(name='lzl',  password='123456')>

獲取全部數據:

#當前數據表信息

mysql> select * from user;
+----+------------+----------+
| id | name       | password |
+----+------------+----------+
|  1 | lianzhilei | 123456   |
|  2 | lzl        | 123456   |
|  3 | lzl        | 123456   |
|  6 | alex       | 34567    |
|  7 | alex       | 34567    |
|  8 | wupeiqi    | 33422    |
+----+------------+----------+
6 rows in set (0.00 sec)

print(Session.query(User.name,User.id).all() )
# [('lianzhilei', 1), ('lzl', 2), ('lzl', 3), ('alex', 6), ('alex', 7), ('wupeiqi', 8)]

多條件查詢:

# 多條件查詢

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy import func

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

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)

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

objs = Session.query(User).filter(User.id>3).filter(User.id<8).all()
print(objs)
# [<User(name='alex',  password='34567')>, <User(name='alex',  password='34567')>]

統計:

# 統計

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy import func

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

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)

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

print(Session.query(User).filter(User.name.like("l%")).count())
#3

分組:

# 分組

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy import func

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

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)

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

print(Session.query(func.count(User.name),User.name).group_by(User.name).all())
#[(2, 'alex'), (1, 'lianzhilei'), (2, 'lzl'), (1, 'wupeiqi')]

至關於原生sql爲

SELECT count(user.name) AS count_1, user.name AS user_name
FROM user GROUP BY user.name

 

四、修改

# 修改

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

class User(Base):
    __tablename__ = "user"      #表名
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    password = Column(String(64))

    def __str__(self):
        return "<User(name='%s',  password='%s')>" % (
        self.name, self.password)

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

my_user = Session.query(User).filter_by(name="lzl").first()
print(my_user)
#<User(name='lzl',  password='123456')>

my_user.name = "lianzhilei"

Session.commit()    #提交數據


mysql> select * from user;
+----+------------+----------+
| id | name       | password |
+----+------------+----------+
|  1 | lianzhilei | 123456   |
|  2 | lzl        | 123456   |
|  3 | lzl        | 123456   |
+----+------------+----------+
3 rows in set (0.00 sec)

 

五、回滾

# 回滾

from sqlalchemy import  create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Integer,Column
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()   #生成orm基類

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)

Session_class = sessionmaker(bind=engine)   #Session_class如今不是實例,而是類
Session = Session_class()   #生成Session實例

my_user = Session.query(User).filter_by(id = 1).first()
my_user.name = "Jack"
print(my_user)
# <User(name='Jack',  password='123456')>

Rain_user = User(name="Rain",password="12345")
Session.add(Rain_user)
print(Session.query(User).filter(User.name.in_(["Jack","Rain"])).all()) # 這時看session裏有你剛添加和修改的數據
#[<User(name='Jack',  password='123456')>, <User(name='Rain',  password='12345')>]

Session.rollback()

print(Session.query(User).filter(User.name.in_(["Jack","Rain"])).all())  #再查就發現剛纔添加的數據沒有了。
#[]

 

 六、外鍵關聯

咱們先建立個study_record表與student進行關聯

# 外鍵關聯

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Column,Integer,ForeignKey,DATE
from sqlalchemy.orm import sessionmaker,relationship

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.0.59/lzl",
                       encoding="utf-8")

Base = declarative_base()

class Student(Base):
    __tablename__ ="student"
    id = Column(Integer,primary_key=True)
    name = Column(String(32),nullable=False)
    register_date = Column(DATE,nullable=False)

    def __repr__(self):
        return "<%s name:%s>"%(self.id,self.name)

class StudyRecord(Base):
    __tablename__ = "study_record"
    id = Column(Integer,primary_key=True)
    day = Column(Integer,nullable=False)
    status = Column(String(32),nullable=False)
    stu_id = Column(Integer,ForeignKey("student.id")) #關聯student表裏的id

    my_student = relationship("Student",backref="my_study_record") # Student爲關聯的類 
    def __repr__(self):
        return "<%s name:%s>" % (self.id, self.name)

Base.metadata.create_all(engine)

Session_class = sessionmaker(bind=engine)
session = Session_class()

s1 = Student(name="lzl",register_date="2016-10-26")
s2 = Student(name="alex",register_date="2015-10-26")
s3 = Student(name="eric",register_date="2014-10-26")
s4 = Student(name="rain",register_date="2013-10-26")

r1 = StudyRecord(day=1,status="YES",stu_id=1)
r2 = StudyRecord(day=2,status="No",stu_id=1)
r3 = StudyRecord(day=3,status="YES",stu_id=1)
r4 = StudyRecord(day=1,status="YES",stu_id=2)

session.add_all([s1,s2,s3,s4,r1,r2,r3,r4])
session.commit()

注:my_student = relationship("Student",backref="my_study_record")這個nb,容許你在user表裏經過backref字段反向查出全部它在addresses表裏的關聯項

查詢:

# 外鍵查詢

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String,Column,Integer,ForeignKey,DATE
from sqlalchemy.orm import sessionmaker,relationship

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.0.59/lzl",
                       encoding="utf-8")

Base = declarative_base()

class Student(Base):
    __tablename__ ="student"
    id = Column(Integer,primary_key=True)
    name = Column(String(32),nullable=False)
    register_date = Column(DATE,nullable=False)

    def __repr__(self):
        return "<id:%s name:%s>"%(self.id,self.name)

class StudyRecord(Base):
    __tablename__ = "study_record"
    id = Column(Integer,primary_key=True)
    day = Column(Integer,nullable=False)
    status = Column(String(32),nullable=False)
    stu_id = Column(Integer,ForeignKey("student.id")) #關聯student表裏的id

    my_student = relationship("Student",backref="my_study_record") # Student爲關聯的類

    def __repr__(self):
        return "<name:%s day:%s status:%s>" % (self.my_student.name,self.day,self.status)

Base.metadata.create_all(engine)

Session_class = sessionmaker(bind=engine)
session = Session_class()

stu_obj = session.query(Student).filter(Student.name=="lzl").first()
print(stu_obj)
#<id:1 name:lzl>

print(stu_obj.my_study_record)
#[<name:lzl day:1 status:YES>, <name:lzl day:2 status:No>, <name:lzl day:3 status:YES>]

  

 七、多外鍵關聯

下表中,Customer表有2個字段都關聯了Address表,首先先建立表結構

# 多外鍵關聯

from sqlalchemy import create_engine
from sqlalchemy import Integer,String,Column,ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker,relationship

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8",echo= True)

Base =  declarative_base()

class Customer(Base):
    __tablename__ = "customer"
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    billing_address_id = Column(Integer,ForeignKey("address.id"))
    shipping_address_id = Column(Integer, ForeignKey("address.id"))

    billing_address = relationship("Address",foreign_keys=[billing_address_id]) #必須寫foreign_keys
    shipping_address = relationship("Address",foreign_keys=[shipping_address_id])

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    street = Column(String(32))
    city = Column(String(32))
    state = Column(String(32))

Base.metadata.create_all(engine)


mysql> desc address;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id     | int(11)     | NO   | PRI | NULL    | auto_increment |
| street | varchar(32) | YES  |     | NULL    |                |
| city   | varchar(32) | YES  |     | NULL    |                |
| state  | varchar(32) | YES  |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> desc customer;
+---------------------+-------------+------+-----+---------+----------------+
| Field               | Type        | Null | Key | Default | Extra          |
+---------------------+-------------+------+-----+---------+----------------+
| id                  | int(11)     | NO   | PRI | NULL    | auto_increment |
| name                | varchar(32) | YES  |     | NULL    |                |
| billing_address_id  | int(11)     | YES  | MUL | NULL    |                |
| shipping_address_id | int(11)     | YES  | MUL | NULL    |                |
+---------------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

生成數據:

Session = sessionmaker(bind=engine)
session = Session()

a1 = Address(street="Tiantongyuan",city="ChangPing",state="BJ")
a2 = Address(street="Wudaokou",city="HaiDian",state="BJ")
a3 = Address(street="Yanjiao",city="LangFang",state="HB")

session.add_all([a1,a2,a3])
c1 = Customer(name="lzl",billing_address_id=1,shipping_address_id=2)
c2 = Customer(name="Alex",billing_address_id=3,shipping_address_id=3)

session.add_all([c1,c2])

session.commit()

查詢數據:

class Customer(Base):
    __tablename__ = "customer"
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    billing_address_id = Column(Integer,ForeignKey("address.id"))
    shipping_address_id = Column(Integer, ForeignKey("address.id"))

    billing_address = relationship("Address",foreign_keys=[billing_address_id]) #必須寫foreign_keys
    shipping_address = relationship("Address",foreign_keys=[shipping_address_id])

    def __repr__(self):
        return "<name:%s billing_add:%s shipping_add:%s>"%(self.name,self.billing_address.street,
                                                           self.shipping_address.street)


#Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

cus_obj = session.query(Customer).filter_by(name="lzl").first()
print(cus_obj)
# <name:lzl billing_add:Tiantongyuan shipping_add:Wudaokou>

  

 八、多對多關聯

如今來設計一個能描述「圖書」與「做者」的關係的表結構,需求是

  1. 一本書能夠有好幾個做者一塊兒出版
  2. 一個做者能夠寫好幾本書

建立表結構:

#一本書能夠有多個做者,一個做者又能夠出版多本書


from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl",
                       encoding="utf-8")

Base = declarative_base()

#建立book_m2m_author表,表不用用戶操做,系統自動維護,自動添加數據
book_m2m_author = Table('book_m2m_author', Base.metadata,
                        Column('book_id',Integer,ForeignKey('books.id')),
                        Column('author_id',Integer,ForeignKey('authors.id')),
                        )

class Book(Base):
    __tablename__ = 'books'
    id = Column(Integer,primary_key=True)
    name = Column(String(64))
    pub_date = Column(DATE)
    #關聯Author類,secondary表示經過book_m2m_author表進行查詢關聯數據,backref反向查詢也同樣
    authors = relationship('Author',secondary=book_m2m_author,backref='books')
    

    def __repr__(self):
        return self.name

class Author(Base):
    __tablename__ = 'authors'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))

    def __repr__(self):
        return self.name

Base.metadata.create_all(engine)

建立表數據: 

#建立數據

Session = sessionmaker(bind=engine)
session = Session()

b1 = Book(name="learn python with Alex",pub_date="2014-05-02")
b2 = Book(name="learn linux with Alex",pub_date="2015-05-02")
b3 = Book(name="learn go with Alex",pub_date="2016-05-02")

a1 = Author(name="Alex")
a2 = Author(name="Jack")
a3 = Author(name="Rain")

#關鍵來了,建立關聯關係
b1.authors = [a1,a3]
b3.authors = [a1,a2,a3]

session.add_all([b1,b2,b3,a1,a2,a3])
session.commit()


mysql> select * from book_m2m_author;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         1 |
|       2 |         1 |
|       2 |         2 |
|       1 |         3 |
|       2 |         3 |
+---------+-----------+
5 rows in set (0.00 sec)

mysql> select * from authors;
+----+------+
| id | name |
+----+------+
|  1 | Alex |
|  2 | Jack |
|  3 | Rain |
+----+------+
3 rows in set (0.00 sec)

mysql> select * from books;
+----+------------------------+------------+
| id | name                   | pub_date   |
+----+------------------------+------------+
|  1 | learn python with Alex | 2014-05-02 |
|  2 | learn go with Alex     | 2016-05-02 |
|  3 | learn linux with Alex  | 2015-05-02 |
+----+------------------------+------------+
3 rows in set (0.00 sec)

查詢:

author_obj = session.query(Author).filter_by(name="Alex").first()
print(author_obj,author_obj.books)

book_obj = session.query(Book).filter_by(id=2).first()
print(book_obj,book_obj.authors)


# Alex [learn python with Alex, learn go with Alex]
# learn go with Alex [Alex, Jack, Rain]

  

九、多對多刪除

刪除數據時不用管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()

 

十、中文

engine = create_engine("mysql+pymysql://root:zyw@123@192.168.20.219/lzl?charset=utf8")


#修改查看數據庫字符編碼
mysql> alter database lzl character set utf8;
Query OK, 1 row affected (0.00 sec)

mysql>  show variables like 'character_set_database';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| character_set_database | utf8  |
相關文章
相關標籤/搜索