SQLAlchemy學習記錄
一、關係定義
(一)一對多關係
onetomany
表示一對多的關係時,在子表類中通過 foreign key (外鍵)引用父表類。
然後,在父表類中通過 relationship() 方法來引用子表的類:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(64), nullable=False, index=True)
password = Column(String(64), nullable=False)
email = Column(String(64), nullable=False, index=True)
articles = relationship('Article')
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.username)
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String(255), nullable=False, index=True)
content = Column(Text)
user_id = Column(Integer, ForeignKey('users.id'))
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.title)
每篇文章有一個外鍵指向 users
表中的主鍵 id
, 而在 User
中使用 SQLAlchemy 提供的 relationship
描述 關係。而用戶與文章的之間的這個關係是雙向的,所以我們看到上面的兩張表中都定義了 relationship
。
SQLAlchemy 提供了 backref
讓我們可以只需要定義一個關係:
articles = relationship('Article', backref='author')
添加了這個就可以不用再在 Article
中定義 relationship
了
(二)一對一關係
一對一是兩張表之間本質上的雙向關係
要做到這一點,只需要在一對多關係基礎上的父表中使用 uselist 參數來表示
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(64), nullable=False, index=True)
password = Column(String(64), nullable=False)
email = Column(String(64), nullable=False, index=True)
# articles = relationship('Article', backref='author')
userinfo = relationship('UserInfo', backref='user', uselist=False)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.username)
class UserInfo(Base):
__tablename__ = 'userinfos'
id = Column(Integer, primary_key=True)
name = Column(String(64))
qq = Column(String(11))
phone = Column(String(11))
link = Column(String(64))
user_id = Column(Integer, ForeignKey('users.id'))
定義方法和一對多相同,只是需要添加 userlist=False
(三)多對多關係
多對多關係會在兩個類之間增加一個關聯的表。
這個關聯的表在 relationship() 方法中通過 secondary 參數來表示。
通常的,這個表會通過 MetaData 對象來與聲明基類關聯,所以這個 ForeignKey 指令會使用鏈接來定位到遠程的表:
定義中間表可以定義中間關係表相關的類,也可以直接通過Base.metdata生成對應關係表對象,不過基於code first準則,還是推薦將中間關係寫成類。
構建第三張關係類實現多對多。
article_tag = Table(
'article_tag', Base.metadata,
Column('article_id', Integer, ForeignKey('articles.id')),
Column('tag_id', Integer, ForeignKey('tags.id'))
)
class Tag(Base):
__tablename__ = 'tags'
id = Column(Integer, primary_key=True)
name = Column(String(64), nullable=False, index=True)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.name)
二、增刪改查
from sqlalchemy import Column, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 連接數據庫
engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test') # 創建數據庫引擎
# 建立會話
DBSession = sessionmaker(bind=engine)
session = DBSession() #類似cursor
# 創建基類
Base = declarative_base()
# 創價類映射到表
class User(Base):
__tablename__ = 'user'
id = Column(String(20), primary_key=True)
name = Column(String(20))
# help(session.add)
# 增加記錄add
new_user = User(id='1', name='lbq')
session.add(new_user)
# 查詢記錄query
user1 = session.query(User).filter(User.name == 'lbq').one()
# 更改記錄
print('更改操作開始')
user1.name = 'nihao'
count_lbq = session.query(User).filter(User.name == 'lbq').count()
print('姓名爲lbq的數量爲', count_lbq)
count_nihao = session.query(User).filter(User.name == 'nihao').count()
print('姓名爲nihao的數量爲', count_nihao)
print('更改操作開始')
# 刪除記錄delete
print('刪除操作開始')
user = session.query(User).filter(User.name == 'nihao').one()
session.delete(user)
user_nihao = session.query(User).filter(User.name == 'nihao').count()
print('姓名爲nihao的數量爲', count_nihao)
print('刪除操作結束')
session.commit()
session.close()
三、類映射到數據庫
方法一
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)
方法二
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://用戶名:密碼@IP/數據庫名稱?charset=utf8")
Base = declarative_base() #生成orm基類,執行SQL語句的類就繼承Base
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(32))
password = Column(String(64))
def __repr__(self): #如果想讓它變的可讀,只需在定義表的類下面加上這樣的代碼
return "<id:%s name:%s password:%s>\n"%(self.id,self.name,self.password)
Base.metadata.create_all(engine) #創建表結構
#1 Base是上面定義的orm父類,metadata.create_all是他的方法
#2 engine是連接數據庫的引擎
#3 執行create_all(engine)將會執行所有繼承Base的語句
四、對應數據庫類型
數據類型 | python數據類型 | 說明 |
---|---|---|
Integer | int | 整形 |
String | str | 字符串 |
Float | float | 浮點型 |
DECIMAL | decimal.Decimal | 定點型 |
Boolean | bool | 布爾型 |
Date | datetime.date | 日期 |
DateTime | datetime.datetime | 日期和時間 |
Time | datetime.time | 時間 |
Enum | str | 枚舉類型 |
Text | str | 文本類型 |
LongText | str | 長文本類型 |
五、基礎指令
檢查sqlalchemy版本
import sqlalchemy
sqlalchemy.__version__
初始化數據庫連接
from sqlalchemy import create_engine
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
創建DBSession類型
DBSession = sessionmaker(bind=engine)
創建對象基類
Base = declarative_base()