SQL炼金术中独立ORM映射类的列继承
我正在尝试使用SQLalchemy中的声明性ORM Mapper类复制以下SQLITE 创建表
语句。
CREATE TABLE IF NOT EXISTS question (
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS solution (
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL,
source_code TEXT NOT NULL,
runtime_complexity TEXT NOT NULL,
storage_complexity TEXT NOT NULL,
understood TEXT NOT NULL
);
是否有一种方法可以在ORM映射器类中指定继承,从而使问题
和解决方案
表保持独立(即对层次结构中的子类查询不应渲染作为SQL在其继承路径中的所有表中加入),同时还减少了下面显示的重复代码的数量?如下注释所示,这些映射类类具有一些具有相同名称和数据类型的相同列,并且具有相同的__ epr __
方法。
from sqlalchemy import Column, Sequence, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Question(Base):
__tablename__ = 'question'
# vvv Both Solution and Question classes have these columns
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
# ^^^
# vvv Both Solution and Question classes have this method
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
# ^^^
class Solution(Base):
__tablename__ = 'solution'
# vvv same in Question class
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
# ^^^
source_code = Column(Integer, nullable=False)
runtime_complexity = Column(Integer, nullable=False)
storage_complexity = Column(Integer, nullable=False)
understood = Column(Integer, nullable=False)
# vvv same in Question class
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
# ^^^
从我在
sqlalchemy支持三种形式的继承形式:
该部分将导致我假设混凝土表继承是我需要的。但是,在“具体表继承”部分下,它读取:
混凝土继承将每个子类映射到其自己独特的表格,每个表都包含产生该类实例所需的所有列。
。
这是我试图完成的工作。 Sqlalchemy是否可以这样的事情?
from sqlalchemy import Column, Sequence, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class QS(Base):
# an abstract class that does NOT map to any table in the database.
# just holds column names and column data types,
# along with methods common to question and solution mapper classes
__abstract__ = True
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
class Question(QS):
__tablename__ = 'question'
# actually maps to table called question
# which has columns id, title, body
class Solution(QS):
__tablename__ = 'solution'
# actually maps to table called solution,
# which has columns id, title, body, source_code, runtime_complexity, and storage_complexity
# (has a few more columns than the base class)
source_code = Column(Integer, nullable=False)
runtime_complexity = Column(Integer, nullable=False)
storage_complexity = Column(Integer, nullable=False)
understood = Column(Integer, nullable=False)
I am trying to replicate the following SQLite CREATE TABLE
statements using the declarative ORM mapper classes in SQLALchemy.
CREATE TABLE IF NOT EXISTS question (
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS solution (
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL,
source_code TEXT NOT NULL,
runtime_complexity TEXT NOT NULL,
storage_complexity TEXT NOT NULL,
understood TEXT NOT NULL
);
Is there a way to specify inheritance in ORM mapper classes such that the question
and solution
tables remain independent (i.e. Querying against a subclass in the hierarchy should not render as an SQL JOIN along all tables in its inheritance path) while also reducing the amount of repeated code shown below? As indicated in the comments below, these mapper classes have some of the same columns with the same names and datatypes, and have the same __repr__
methods.
from sqlalchemy import Column, Sequence, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Question(Base):
__tablename__ = 'question'
# vvv Both Solution and Question classes have these columns
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
# ^^^
# vvv Both Solution and Question classes have this method
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
# ^^^
class Solution(Base):
__tablename__ = 'solution'
# vvv same in Question class
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
# ^^^
source_code = Column(Integer, nullable=False)
runtime_complexity = Column(Integer, nullable=False)
storage_complexity = Column(Integer, nullable=False)
understood = Column(Integer, nullable=False)
# vvv same in Question class
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
# ^^^
From what I read in the Mapping Class Inheritance Hierarchies page in the SQLAlchemy docs, there are three methods of inheritance:
SQLAlchemy supports three forms of inheritance:
- single table inheritance, where several types of classes are represented by a single table.
- concrete table inheritance, where each type of class is represented by independent tables.
- joined table inheritance, where the class hierarchy is broken up among dependent tables, each class represented by its own table that only includes those attributes local to that class..
That section would lead me to assume that concrete table inheritance is what I need. However, under the concreate table inheritance section, it reads:
Concrete inheritance maps each subclass to its own distinct table, each of which contains all columns necessary to produce an instance of that class.
Here's what I'm trying to accomplish (roughly). Is something like this possible in SQLAlchemy?
from sqlalchemy import Column, Sequence, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class QS(Base):
# an abstract class that does NOT map to any table in the database.
# just holds column names and column data types,
# along with methods common to question and solution mapper classes
__abstract__ = True
id = Column(Integer, Sequence('id_seq'), primary_key=True)
title = Column(String, nullable=False)
body = Column(Integer, nullable=False)
def __repr__(self):
class_name = self.__class__.__name__
column_names = tuple(col.name for col in self.__table__.columns)
return f"<{class_name}{column_names}>"
class Question(QS):
__tablename__ = 'question'
# actually maps to table called question
# which has columns id, title, body
class Solution(QS):
__tablename__ = 'solution'
# actually maps to table called solution,
# which has columns id, title, body, source_code, runtime_complexity, and storage_complexity
# (has a few more columns than the base class)
source_code = Column(Integer, nullable=False)
runtime_complexity = Column(Integer, nullable=False)
storage_complexity = Column(Integer, nullable=False)
understood = Column(Integer, nullable=False)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
感谢 @rfkortekaas '评论,建议使用 mixin类,我能够声明
问题
document code 和解决方案
继承。Thanks to @rfkortekaas' comment, which suggested the use of Mixin Classes, I was able to declare the parent class
Document
from whichQuestion
andSolution
inherit.