sqlalchemy_No5_创建数据表模型类

  • Post author:
  • Post category:其他

创建步骤

1. 创建元数据

元数据的概念

sqlalchemy中一个重要的元素是SQL Expression Language(用来生成sql语句的)。而它的实现就是用一些Python对象来表示数据库中的表和列等概念。这些Python对象就称为元数据。
最常用的sqlalchemy中的元数据是MetaData,Table和Colum类。

元数据的创建方法

在sqlalchemy中创建元数据用来存储应用中所有数据表。通常一个应用中只有一个元数据。

方式1:直接方式

利用SQL alchemy包中的MetaData类生成。

from sqlalchemy import MetaData
metadata_obj = MetaData()

方式2:ORM方式

利用SQL alchemy下orm子包中的registry类下的metadata()函数生成。

from sqlalchemy.orm import registry
mapper_registry = registry()
metadata_obj = mapper_registry.metadata()

2. 声明表数据

当我们创建项目与数据库交互的过程中,通常会出现如下两种情况:1.数据库中还没有相应的数据表,需要我们创建数据表。2.数据库中已经有相应的数据表,需要我们创建与之对应的数据模型类。
针对第一种方式我们通常称为声明式方式,第二种方式我们通常称为反射式方式。这一个章节主要讲述声明式方式。
在SQL alchemy中通常存在三种方式进行声明式创建数据表,分别是通过Table类,通过ORM类,通过混合方式。

方式1:Table方式

Table方式就是利用SQL alchemy中的Table类来创建数据表模型。

from sqlalchemy import Table,Column,String,Integer,ForeignKey

user_table = Table(
	#定义表的名称
	"user",
	#定义存放在哪个元数据中
	metadata_obj,
	#定义各字段
	Column("id",Integer,primary_key=True,autoincrement=True),
	Column("name",String(30),nullable=False),
	Column("fullname",String(50))	
)
address_table = Table(
	"address",
	metadata_obj,
	Column("id",Integer,primary_key=True,autoincrement=True),
	Column("user_id",ForeignKey("user.id"),nullable=False),
	Column("email_address",String(50))
)

方式2:ORM方式

ORM方式就是利用定义类的方式创建数据表。

创建基类

由于要创建一个数据表的模型类,故要首先基于一个固定的父类,来创建相应的类,这样才能被python认为是一个数据表模型类。

方法1

利用registry实例对象的generate_base函数创建。

from sqlalchemy.orm import registry
mapper_registry = registry()
Base = mapper_registry.generate_base()
方法2

利用SQL alchemy的orm子包中的declarative_base函数创建。

from sqlalchemy.orm import declarative_base
Base = declarative_base()

自定义类

要创建自定义的数据表模型类,需要继承基类。

from sqlalchemy.orm import relationship
class User(Base):
	#定义表名称
	__tablename__ = "user"
	#定义各列id等为列名
	id = Column(Integer,primary_key=True,autoincrement=True)
	name = Column(String(30))
	fullname = Column(String(50))
	# 定义外键关系,Address表示类,user表示Address类中relationship的名字
	address = relationship("Address",back_populates="user")
	# 定义类的字符串表现形式,!r表示利用对象的__repr__方法返回
	def __repr__(self):
		return f"User(id={self.id!r},name={self.name!r},fullname={self.fullname!r})"

class Address(Base):
	 __tablename__ = "address"
    id = Column(Integer,primary_key = True)
    email_address = Column(String,nullable = False)
    user_id = Column(Integer,ForeignKey("user_account.id"))
    # 定义外键关系,User表示类,address表示User类中relationship的名字
    user = relationship("User",back_populates="address")
    def __repr__(self) -> str:
        return f"Address(id={self.id!r},email_address={self.email_address!r})"

方式3:混合方式

通过观察上面两种方式发现,ORM方式中定义各列的部分和Table方式基本一致。故这里可以用这两种方式的混合方式来创建数据表模型类。

from sqlalchemy import Table,Column,String,Integer,ForeignKey
from sqlalchemy.orm import relationship,registry
mapper_registry = registry()
metadata_obj = mapper_registry.metadata()
user_table = Table(
	#定义表的名称
	"user",
	#定义存放在哪个元数据中
	metadata_obj,
	#定义各字段
	Column("id",Integer,primary_key=True,autoincrement=True),
	Column("name",String(30),nullable=False),
	Column("fullname",String(50))	
)
address_table = Table(
	"address",
	metadata_obj,
	Column("id",Integer,primary_key=True,autoincrement=True),
	Column("user_id",ForeignKey("user.id"),nullable=False),
	Column("email_address",String(50))
)
Base = mapper_registry.generate_base()
class User(Base):
	__table__ = user_table
	address = relationship("Address",back_populates="user")
	def __repr__(self):
		return f"User(id={self.id!r},name={self.name!r},fullname={self.fullname!r})"
class Address(Base):
	__table__ = address_table
	user = relationship("User",back_populates="address")
    def __repr__(self) -> str:
        return f"Address(id={self.id!r},email_address={self.email_address!r})"

3. 反射数据表

反射数据表就是根据数据库中已经存在的数据表,自动生成其对应的数据表模型类。

from sqlalchemy import MetaData,create_engine
metadata_obj = MetaData()
url="mysql+pymysql://root:123456@127.0.0.1:3306/testdb"
engine = create_engine(url)
some_table = Table("some_table", metadata_obj, autoload_with=engine)

4.与数据库交互

创建表

利用metadata实例对象的create_all方法来在指定的数据库中创建其包含的所有的数据表。

metadata_obj.create_all(engine)

删除表

利用metadata实例对象的drop_all方法来在指定的数据库中删除其包含的所有的数据库表。

metadata_obj.drop_all(engine)

示例代码

声明式创建数据库表

from importlib.metadata import metadata
from sqlalchemy import Table,Column,Integer,String,ForeignKey,create_engine
from sqlalchemy.orm import declarative_base,relationship
dburl = 'mysql+pymysql://root:123456@127.0.0.1:3306/testdb'
engine = create_engine(dburl)
Base = declarative_base()
metadata_obj = Base.metadata
user_table = Table(
    "user",
    metadata_obj,
    Column("id",Integer,primary_key=True,autoincrement=True),
    Column("name",String(30))
)
address_table = Table(
    "address",
    metadata_obj,
    Column("id",Integer,primary_key=True,autoincrement=True),
    Column("email_address",String(200)),
    Column("user_id",ForeignKey("user.id"),nullable=False)
)
class User(Base):
    __table__ = user_table
    address = relationship("Address",back_populates="user")
    def __repr__(self):
        return f'User(name={self.name!r})'
class Address(Base):
    __table__ = address_table
    user = relationship("User",back_populates="address")
    def __repr__(self):
        return f'Address(email_address={self.email_address!r},user={self.user!r})'
def create_table(metadata,engine):
    metadata.create_all(engine)
if __name__ == "__main__":
    create_table(metadata_obj,engine)

在这里插入图片描述

反射式创建数据表模型

from sqlalchemy import create_engine,Table
from sqlalchemy.orm import declarative_base,Session
urldb = 'mysql+pymysql://root:123456@127.0.0.1:3306/testdb'
engine = create_engine(urldb)
Base = declarative_base()
metadata_obj = Base.metadata

# 利用Table中的autoload自动生成对应的表
stu_table = Table("student",metadata_obj,autoload_with=engine)

class Student(Base):
    __table__ = stu_table
    def __repr__(self) -> str:
        return f"Student(name={self.name!r},age={self.age!r})"
# 向数据库中插入数据
def insert_stu(name:str,age:int):
    with Session(engine) as session:
        stu = Student(name=name,age=age)
        session.add(stu)
        session.commit()

if __name__ == "__main__":
    insert_stu("Jack",12)

在这里插入图片描述


版权声明:本文为baidu_38766791原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。