SQLAlchemy一對一關係實現:
在一對多的條件下:給Article表中添加article,只需要將article放入到user的article屬性中,再將user添加到user表中即可,此時的article會自動添加到Article表中。
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
uid = Column(Integer, ForeignKey("user.id", ondelete="RESTRICT"), nullable=False) # 創建外鍵
# ondelete表示的是外鍵的約束
author = relationship("User", backref="articles") # relationship 一個Article對應一個author
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
article1 = Article(title="new art 1", content="ct111")
article2 = Article(title="new art 2", content="ct222")
article3 = Article(title="new art 3", content="ct333")
user = User(username="ghost")
user.articles.extend([article1, article2, article3])
db_session.add(user)
db_session.commit()
# 此時,user被添加到User表中,而所有的文章添加到了Article表中,uid是當前添加的user
在一對一的條件下,也可以進行添加,例如,通過添加article,實現將user添加到User中
article1 = Article(title="the Knight", content="ktkt111")
user = User(username="knight")
# 一對一直接賦值即可
article1.author = user
db_session.add(article1)
db_session.commit()
一對一關係的實現:
舉例: 在後臺會存儲用戶的信息,但是用戶信息中有常用的字段(例如,username, id, sex)以及不常用的字段,例如address, email等信息,那麼爲了提高數據庫的查找效率,可以對用戶的存儲進行優化,將常用的用戶信息存放到user表中,將不常用的用戶信息存放到user_extend表中,則這兩個表的關係就是一對一的關係。
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
uid = Column(Integer, ForeignKey("user.id", ondelete="RESTRICT"), nullable=False) # 創建外鍵
# ondelete表示的是外鍵的約束
author = relationship("User", backref="articles") # relationship 一個Article對應一個author
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
# 因爲一個User只能對應一個user_extend,必須是一對一的關係
extend = relationship("UserExtend", uselist=False)
# uselist表示使用列表,默認爲True, 表示User下的extend是一個列表,則表示extend不唯一
# 由於extend需要與user一一對應,所以將uselist參數設置爲False,此時表示extend是唯一的
def __repr__(self):
return str(self.id) + " | " + self.username
class UserExtend(Base):
__tablename__ = "user_extend"
id = Column(Integer, primary_key=True, autoincrement=True)
school = Column(String(50), nullable=True)
address = Column(String(50), nullable=False)
email = Column(String(50), nullable=False)
uid = Column(Integer, ForeignKey("user.id", ondelete="RESTRICTION"))
# 在orm層面做關聯
user = relationship("User")
article1 = Article(title="the Knight", content="ktkt111")
user = User(username="knight")
通過這樣的設置,user和user_extend則會成爲一一對應,但是此時不能再設置backref參數爲extend
還有一種方法,即通過backref函數設置backref參數設置。
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
uid = Column(Integer, ForeignKey("user.id", ondelete="RESTRICT"), nullable=False) # 創建外鍵
# ondelete表示的是外鍵的約束
author = relationship("User", backref="articles") # relationship 一個Article對應一個author
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
class UserExtend(Base):
__tablename__ = "user_extend"
id = Column(Integer, primary_key=True, autoincrement=True)
school = Column(String(50), nullable=True)
address = Column(String(50), nullable=False)
email = Column(String(50), nullable=False)
uid = Column(Integer, ForeignKey("user.id", ondelete="RESTRICTION"))
# 在orm層面做關聯
user = relationship("User", backref=backref("extend", uselist=False))
article1 = Article(title="the Knight", content="ktkt111")
user = User(username="knight")
多對多的關係實現:
舉例:在博客上,一篇文章的標籤有多個,一個標籤也可能對應多篇文章,這是一個典型的多對多的關係。
如果需要定義一個多對多的關係,那麼首先需要將兩個做多對多的模型定義出來,使用Table定義一箇中間表,中間表一般只包含兩個模型的外鍵字段,讓這兩個字段的組合作爲中間表的複合主鍵,在多對多的兩個模型上,隨便選擇一個,做一個relationship,同時定義secondary參數爲中間表。
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
article_tag = Table(
"article_tag", # 數據庫的名字
Base.metadata, # 元數據
Column("article_id", Integer, ForeignKey("article.id"), primary_key=True),
Column("tag_id", Integer, ForeignKey("tag.id"), primary_key=True),
# 這個表中沒有主鍵,可以將article_id和tag_id一起作爲一個複合主鍵
# 假設user表中 article_id/title = 1/"cxcx"
# tag表中,tag_id / tag_name = 1/"leisure"
# 則數據表article_tag 中會插入 article_id/tag_id = 1/1
# 爲了減少數據存儲的冗餘,因該只能插入一次 article_id/tag_id = 1/1,
# 所以可以將他們的組合作爲一個複合主鍵
)
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
tags = relationship("Tag", backref="articles", secondary=article_tag)
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
class Tag(Base):
__tablename__ = "tag"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + "|" + self.name
# 創建表
# Base.metadata.drop_all()
# Base.metadata.create_all()
# 插入數據
# article1 = Article(title="gone to xxx")
# article2 = Article(title="Leave now")
#
# tag1 = Tag(name="scary")
# tag2 = Tag(name="horrible")
# article1.tags.extend([tag1, tag2])
#
# tag3 = Tag(name="funny")
# article2.tags.extend([tag2, tag3])
#
# db_session.add_all([article1, article2])
# db_session.commit()
# 數據查詢
articles = db_session.query(Article).all()
for article in articles:
tag_str = []
for tag in article.tags:
tag_str.append(tag.name)
print(article.title, " ", tag_str)
查詢的效果:
ORM層面刪除數據注意事項:
外鍵以及外鍵約束是數據庫層面,下面介紹以下基於ORM層面的約束。例如,在數據庫層面有一個約束叫restrict,代表限制刪除,即如果要刪除父表的數據,但是由於從表也能用到了父表的數據,所以數據庫是拒絕刪除的。但是在ORM層面,如果指定了級聯刪除,那麼ORM就會無視數據庫的RESTRICT約束,先把從表中的數據刪除,然後再將從表中的數據刪除。這樣就實現了級聯刪除。
orm層面刪除數據會無視MySQL層面的外鍵約束,直接會將對應的數據刪除,然後將從表中的外鍵設置爲空,如果想要避免這種行爲,應該將從表中的null設置爲False.
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
uid = Column(Integer, ForeignKey("user.id"), nullable=False)
author = relationship("User", backref="articles")
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
# Base.metadata.drop_all()
# Base.metadata.create_all()
#
# user1 = User(username="Topic")
# article1 = Article(title="Gone with u")
# article1.author = user1
# db_session.add(article1)
# db_session.commit()
# 在orm層面會直接刪除數據,
# orm會先將article的uid設置爲null,然後再將user表中的數據刪除
# 爲了限制這種默認的行爲,可以將uid的nullable屬性設置爲False
user = db_session.query(User).first()
db_session.delete(user)
db_session.commit()
orm層面的CASCADE刪除
在SQLAlchemy中,只要將一個數據添加到session中,和它相關聯的數據都可以一起存儲到數據庫中。這是通過relationship的時候,有一個關鍵字參數cascade可以設置這些屬性。cascade的屬性值有:
1. save-update:默認值,表示在添加一條數據的時候,會把其他和它相關聯的數據都添加到數據庫中。
2. delete:表示刪掉某一模型中的數據的時候,是否刪除掉使用relationship關聯的數據。
3. delete-orphan:表示當對一個ORM對象解除了父表中的關聯對象的時候,自己便會被刪除掉。當然如果父表中的數據被刪除,自己也會被刪除。這個選項只能用在一對多上,不能用在多對多以及多對一上。並且還需要在子模型的relationship中,增加一個single_parent=True的參數。
4. merge:默認選型。當在使用session.merge合併一個對象的時候,會將使用了relationship相關聯的對象進行merge操作。
5. expunge: 移除操作的時候,會將相關聯的對象也進行移除,這個操作只是從session中移除,並不會真正從數據庫中移除。
6. all:是對save-update,merge,refresh-expire, expunge,delete的集中縮寫
# 數據庫層面定義
uid = Column(Integer, ForeignKey("user.id", cascade="save-update, delete"))
如果需要實現,刪除文章的時候,將相關的作者刪除,則可以設置cascade
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
# 數據庫層面定義
uid = Column(Integer, ForeignKey("user.id"))
# orm層面定義
author = relationship("User", backref="articles", cascade="save-update, delete")
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
如果需要實現,刪除文章的時候,刪除相關的作者,或者刪除作者的時候,同時刪除相關的文章,則可以在user中也定義一個relationship.
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
articles = relationship("Article", cascade="save-update,delete")
def __repr__(self):
return str(self.id) + " | " + self.username
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
# 數據庫層面定義
uid = Column(Integer, ForeignKey("user.id"))
# orm層面定義
author = relationship("User", cascade="save-update,delete")
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
例如,可以再定義一張表,comment:
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
# 這裏可以用backref函數在子表中實現
articles = relationship("Article", cascade="save-update,delete") # user刪除,對應的article會刪除
comments = relationship("Comment") # user刪除,對應的comment不會刪除
def __repr__(self):
return str(self.id) + " | " + self.username
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
# 數據庫層面定義
uid = Column(Integer, ForeignKey("user.id"))
# orm層面定義
author = relationship("User", cascade="save-update,delete")
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
class Comment(Base):
__tablename__ = "comment"
id = Column(Integer, primary_key=True, autoincrement=True)
content = Column(String(50), nullable=False)
uid = Column(Integer, ForeignKey("user.id"))
author = relationship("User")
def __repr__(self):
return str(self.id) + " | " + self.content
# Base.metadata.drop_all()
# Base.metadata.create_all()
user1 = User(username="Top")
article1 = Article(title="Gone with wind")
article2 = Article(title="Jane")
comment1 = Comment(content="good")
comment2 = Comment(content="great works")
user1.articles.append(article1)
user1.articles.append(article2)
user1.comments.append(comment1)
user1.comments.append(comment2)
db_session.add(user1)
db_session.commit()
數據庫中的排序:三種排序方法:
1. orderby
在數據庫中插入數據:
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False, default=datetime.now)
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.create_time)
# Base.metadata.drop_all()
# Base.metadata.create_all()
# article = Article(title="title3")
# db_session.add(article)
# db_session.commit()
articles = db_session.query(Article).order_by(Article.create_time.desc()) # 反向排序
# articles = db_session.query(Article).order_by("~article.create_time") # 反向排序
for article in articles:
print(article)
排序結果:
2. 定義模型的時候,傳遞orderby參數
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False, default=datetime.now)
# 定義排序的方式
__mapper_args__ = {
"order_by": create_time.desc()
}
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.create_time)
# Base.metadata.drop_all()
# Base.metadata.create_all()
# article = Article(title="title3")
# db_session.add(article)
# db_session.commit()
articles = db_session.query(Article).all() # 反向排序
# articles = db_session.query(Article).order_by("~article.create_time") # 反向排序
for article in articles:
print(article)
3. 在定義relationship的時候,可以傳遞order_by參數,指定排序方式
在存在主表以及父表的時候,通過relationship中的參數指定排序方式
首先在表中插入數據:
示例代碼:
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
from datetime import datetime
import random
from sqlalchemy import Table
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False, default=datetime.now)
uid = Column(Integer, ForeignKey("user.id"))
# 通過user拿到user下的所有的文章的時候,可以通過時間排序
author = relationship("User", backref=backref("articles", order_by=create_time.desc()))
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.create_time)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
# Base.metadata.drop_all()
# Base.metadata.create_all()
# article1 = Article(title="title1")
# article2 = Article(title="title2")
# user = db_session.query(User).filter(User.username == "toc").first()
# user.articles.append(article2)
#
# db_session.add(user)
# db_session.commit()
user = db_session.query(User).first()
articles = user.articles
for article in articles:
print(article)
查詢結果:
排序的默認方式是從小到大,如果需要反過來,可以使用這個字段的desc()方法。
limit,offset,以及切片操作:
limit:可以限制每次查找的時候只查詢幾條數據
offset:可以限制查詢數據的時候過濾掉前面多少條數據
slice:可以對query()對象使用切片操作
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
from datetime import datetime
import random
from sqlalchemy import Table
import time
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False, default=datetime.now)
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.create_time)
# Base.metadata.drop_all()
# Base.metadata.create_all()
# 插入數據
# for x in range(100):
# title = "title" + str(x+1)
# article = Article(title=title)
# time.sleep(1)
# db_session.add(article)
# db_session.commit()
# print("current {}".format(x))
# # 查詢limit
articles = db_session.query(Article).limit(10).all()
for article in articles:
print(article)
# 查詢offset
print("-"*50)
articles1 = db_session.query(Article).offset(10).limit(10).all() # 從第11條開始,查找10條
for article in articles1:
print(article)
# 查詢slice
print("-"*50)
articles2 = db_session.query(Article).slice(20, 30).all()
for article in articles2:
print(article)
數據查詢懶加載技術:
在一對多,或者多對多的時候,如果想要獲取多的這一部分的數據的時候,通常來講,通過一個屬性就可以全部獲取,例如上面用到的user.artices就可以獲取全部的文章。但是有的時候並不像獲取全部的數據,指向獲取這個作者今天發佈的文章,或者只是想展示少部分的數據。可以通過給relationship傳遞一個lazy=dynamic,那麼以後通過user.articles獲取到的就不是一個列表,而是一個AppendQuery對象,可以對這個對象在進行一層過濾和排序操作。
如果採用將所有的數據從數據庫中拿出來再進行過濾的話,就會比較耗費性能。上述的方法稱爲懶加載。
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, func
from sqlalchemy import Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
from datetime import datetime
import random
from sqlalchemy import Table
import time
HOST_NAME = "127.0.0.1"
PORT = "3306"
DATABASE = "cms"
USERNAME = "root"
PASSWORD = "root1234"
# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}".format(
username=USERNAME, password=PASSWORD, host=HOST_NAME, port=PORT, database=DATABASE
)
# 創建數據庫引擎
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 通過繼承Base創建ORM模型/ 創建基類
db_session = sessionmaker(engine)() # 創建會話,才能實現增刪改查
# 1. 創建ORM模型,必須繼承自SQLAlchemy:
# 2. 在ORM中創建一些屬性,跟表中的字段一一映射,這些屬性必須是SQLAlchemy提供的數據類型
# 3. 將創建好的ORM模型映射到數據庫中
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), nullable=False)
def __repr__(self):
return str(self.id) + " | " + self.username
class Article(Base):
__tablename__ = "article"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
# 數據庫層面定義
uid = Column(Integer, ForeignKey("user.id"))
# orm層面定義
author = relationship("User", backref=backref("articles", lazy="dynamic")) # 懶加載
def __repr__(self):
return "<article>" + str(self.id) + " | " + self.title + " | " + " | " + str(self.uid)
user = db_session.query(User).first()
print(type(user.articles))
articles = user.articles.filter(Article.id > 50).all() # user.articles可以直接使用filter進行過濾
for article in articles:
print(article)
# user.articles 是一個<class 'sqlalchemy.orm.dynamic.AppenderQuery'>
# 所以除了可以使用filter的方法
# 也可以使用append方法添加新的數據,再次commit到數據庫中。
article_new = Article(title="new article")
user.articles.append(article_new)
db_session.commit()
lazy的屬性值:
1. select, 默認值,例如,如果沒有訪問user.articles,sqlalchemy就不會從數據庫中查找數據,一旦訪問了這個屬性,sqlalchemy就會從數據庫查找所有的數據,返回的數據是一個list對象,這也是懶加載。
2. dynamic:在訪問user.articles屬性的時候,返回的是一個AppendQuery對象。
-----------------------------------------------------------------------------------------------------------