在 vanilla SQLAlchemy 中创建关系
Creating Relationships in vanilla SQLAlchemy
我最近开始将 SQLAlchemy 用于我正在处理的数据库应用程序。事情进展顺利,直到我需要关系。我查看了文档并找出了该怎么做。但是,它仅在我的模型位于同一个 .py 文件中时才有效。这对我来说有点混乱,所以我试图将它们分离到它们自己的 model_name.py 文件中。例如:
frame_model.py:
from __future__ import annotations
from .db_connector import master_session, db_engine
from sqlalchemy import Column, String, Integer, Date, Computed, ForeignKey, cast, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.types import TypeDecorator
from datetime import datetime
# Create ts_vector type.
class TSVector(TypeDecorator):
impl = TSVECTOR
cache_ok = True
base = declarative_base()
class FrameModel(base):
__tablename__ = "inventory"
frame_id: int = Column(Integer, primary_key=True, autoincrement=True)
frame_name: str = Column(String(140), nullable=False)
quantity: int = Column(Integer, nullable=False)
frame_size: str = Column(String(45), nullable=False)
colour: str = Column(String(100), nullable=False)
price: int = Column(Integer, nullable=False)
frame_category: str = Column(
String(100),
ForeignKey("categories.category", ondelete="CASCADE"),
nullable=False,
)
date_entered: Date = Column(
Date, default=datetime.today().strftime("%Y-%m-%d"), nullable=False
)
frame_code: str = Column(String(50), nullable=False)
__ts_vector__ = Column(
TSVector(),
Computed(
"to_tsvector('english', frame_name || ' ' || frame_size || ' ' || colour || ' ' || frame_category || ' ' || frame_code )",
persisted=True,
),
)
sale = relationship("SaleModel")
__table_args__ = (Index("idx_frame_fts", __ts_vector__, postgresql_using="gin"),)
def __repr__(self) -> str:
return f"<{self.__class__.__name__}: {self.frame_name}, Category: {self.frame_category}>"
def save_to_db(self):
master_session.add(self)
master_session.commit()
def delete_from_db(self):
master_session.delete(self)
master_session.commit()
base.metadata.create_all(db_engine)
sale_model.py:
from __future__ import annotations
from sqlalchemy.orm import relationship
from .db_connector import db_engine, master_session
from sqlalchemy import (
Column,
String,
Integer,
Date,
UniqueConstraint,
ForeignKey,
Computed,
cast,
Index,
UniqueConstraint,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.types import TypeDecorator
from datetime import datetime
class TSVector(TypeDecorator):
impl = TSVECTOR
cache_ok = True
base = declarative_base()
class SaleModel(base):
__tablename__ = "sales"
order_id = Column(Integer, primary_key=True, autoincrement=True)
frame = Column(String(100), nullable=False)
quantity_sold = Column(Integer, nullable=False)
customer = Column(String(200), nullable=False)
receipt_num = Column(String(50), nullable=False)
frame_id = Column(Integer, ForeignKey("inventory.frame_id", ondelete="SET NULL"))
frame_code = Column(String(50), nullable=False)
item_price = Column(Integer, nullable=False)
category = Column(String(100), nullable=False)
colour = Column(String(100), nullable=False)
size = Column(String(45), nullable=False)
date_sold = Column(
Date, default=datetime.today().strftime("%Y-%m-%d"), nullable=False
)
__ts_vector__ = Column(
TSVector(),
Computed(
"to_tsvector('english', frame || ' ' || frame_code || ' ' || receipt_num || ' ' || customer)",
persisted=True,
),
)
frame = relationship("FrameModel")
__table_args__ = (
Index("sale_idx", __ts_vector__, postgresql_using="gin"),
UniqueConstraint("receipt_num", name="_receipt_num_uc"),
)
def __repr__(self) -> str:
return f"<Receipt number: {self.receipt_num}, customer: {self.customer}, frame: {self.frame}>"
# Add and update the sale
def save_to_db(self):
master_session.add(self)
master_session.commit()
# Delete the sale
def delete_from_db(self):
master_session.delete(self)
master_session.commit()
base.metadata.create_all(db_engine)
但这一直给我错误:
sqlalchemy.exc.NoReferencedTableError: 找不到与列 'sales.frame_id' 相关联的外键 table 'inventory' 用于生成目标列 'frame_id'[ 的外键=12=]
我尝试了所有方法,从将父项 class 导入子项 class 并在父项 class 中创建引用子项的关系(sale = relationship("sale" , backref="inventory) 但到目前为止没有任何效果。任何指导将不胜感激。
注意:.py 文件位于名为“models”的文件夹中,该文件夹本身有一个空白的 init.py 文件。
多亏了@snakecharmerb 的建议和一些额外的工作,我才能够解决这个问题。
在 sale_model.py 中,我导入了 FrameModel class 并添加了行:
frame = relationship("FrameModel", back_populates="sale")
我最近开始将 SQLAlchemy 用于我正在处理的数据库应用程序。事情进展顺利,直到我需要关系。我查看了文档并找出了该怎么做。但是,它仅在我的模型位于同一个 .py 文件中时才有效。这对我来说有点混乱,所以我试图将它们分离到它们自己的 model_name.py 文件中。例如:
frame_model.py:
from __future__ import annotations
from .db_connector import master_session, db_engine
from sqlalchemy import Column, String, Integer, Date, Computed, ForeignKey, cast, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.types import TypeDecorator
from datetime import datetime
# Create ts_vector type.
class TSVector(TypeDecorator):
impl = TSVECTOR
cache_ok = True
base = declarative_base()
class FrameModel(base):
__tablename__ = "inventory"
frame_id: int = Column(Integer, primary_key=True, autoincrement=True)
frame_name: str = Column(String(140), nullable=False)
quantity: int = Column(Integer, nullable=False)
frame_size: str = Column(String(45), nullable=False)
colour: str = Column(String(100), nullable=False)
price: int = Column(Integer, nullable=False)
frame_category: str = Column(
String(100),
ForeignKey("categories.category", ondelete="CASCADE"),
nullable=False,
)
date_entered: Date = Column(
Date, default=datetime.today().strftime("%Y-%m-%d"), nullable=False
)
frame_code: str = Column(String(50), nullable=False)
__ts_vector__ = Column(
TSVector(),
Computed(
"to_tsvector('english', frame_name || ' ' || frame_size || ' ' || colour || ' ' || frame_category || ' ' || frame_code )",
persisted=True,
),
)
sale = relationship("SaleModel")
__table_args__ = (Index("idx_frame_fts", __ts_vector__, postgresql_using="gin"),)
def __repr__(self) -> str:
return f"<{self.__class__.__name__}: {self.frame_name}, Category: {self.frame_category}>"
def save_to_db(self):
master_session.add(self)
master_session.commit()
def delete_from_db(self):
master_session.delete(self)
master_session.commit()
base.metadata.create_all(db_engine)
sale_model.py:
from __future__ import annotations
from sqlalchemy.orm import relationship
from .db_connector import db_engine, master_session
from sqlalchemy import (
Column,
String,
Integer,
Date,
UniqueConstraint,
ForeignKey,
Computed,
cast,
Index,
UniqueConstraint,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.types import TypeDecorator
from datetime import datetime
class TSVector(TypeDecorator):
impl = TSVECTOR
cache_ok = True
base = declarative_base()
class SaleModel(base):
__tablename__ = "sales"
order_id = Column(Integer, primary_key=True, autoincrement=True)
frame = Column(String(100), nullable=False)
quantity_sold = Column(Integer, nullable=False)
customer = Column(String(200), nullable=False)
receipt_num = Column(String(50), nullable=False)
frame_id = Column(Integer, ForeignKey("inventory.frame_id", ondelete="SET NULL"))
frame_code = Column(String(50), nullable=False)
item_price = Column(Integer, nullable=False)
category = Column(String(100), nullable=False)
colour = Column(String(100), nullable=False)
size = Column(String(45), nullable=False)
date_sold = Column(
Date, default=datetime.today().strftime("%Y-%m-%d"), nullable=False
)
__ts_vector__ = Column(
TSVector(),
Computed(
"to_tsvector('english', frame || ' ' || frame_code || ' ' || receipt_num || ' ' || customer)",
persisted=True,
),
)
frame = relationship("FrameModel")
__table_args__ = (
Index("sale_idx", __ts_vector__, postgresql_using="gin"),
UniqueConstraint("receipt_num", name="_receipt_num_uc"),
)
def __repr__(self) -> str:
return f"<Receipt number: {self.receipt_num}, customer: {self.customer}, frame: {self.frame}>"
# Add and update the sale
def save_to_db(self):
master_session.add(self)
master_session.commit()
# Delete the sale
def delete_from_db(self):
master_session.delete(self)
master_session.commit()
base.metadata.create_all(db_engine)
但这一直给我错误:
sqlalchemy.exc.NoReferencedTableError: 找不到与列 'sales.frame_id' 相关联的外键 table 'inventory' 用于生成目标列 'frame_id'[ 的外键=12=]
我尝试了所有方法,从将父项 class 导入子项 class 并在父项 class 中创建引用子项的关系(sale = relationship("sale" , backref="inventory) 但到目前为止没有任何效果。任何指导将不胜感激。
注意:.py 文件位于名为“models”的文件夹中,该文件夹本身有一个空白的 init.py 文件。
多亏了@snakecharmerb 的建议和一些额外的工作,我才能够解决这个问题。
在 sale_model.py 中,我导入了 FrameModel class 并添加了行:
frame = relationship("FrameModel", back_populates="sale")