如何在SqlAlchemy中自动创建多对多的映射表?

时间:2018-04-11 08:15:11

标签: python python-3.x sqlalchemy

我正在编写一个框架来帮助人们有效地处理数据库中的不同数据模型(意味着批量操作)。我想为多对多关系创建一个基类,可以这样使用:

from sqlalchemy import MetaData
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()    

class CustomBase(Base):
    __abstract__ = True
    metadata = MetaData()

class CustomManyToManyBase(CustomBase):
    __abstract__ = True

class Parent(CustomBase):
   __tablename__ = 'parents'
   id = Column(Integer, primary_key=True)

class Child(CustomBase):
   __tablename__ = 'children'
   id = Column(Integer, primary_key=True)

class Family(CustomManyToManyBase):
   models = (Parent, Child)

然后它将自动获取模型的主键并为关联表创建必要的列,与此相当(就像我写了以下内容):

class Family(CustomBase):
   parent_id = ForeignKey('parent.id')
   child_id = ForeignKey('child.id')

根据我的理解,我不能使用relationship(),因为它在批量操作中被省略,但我可以轻松地从我的数据中提取密钥对,并使用bulk_insert_mappings。我需要其他通用数据操作任务的模型类,所以我认为可能有一种方法可以使用该信息来创建必要的列。

如果我想在该关联表中存储其他信息该怎么办?

这一点的重点是提供一个预编写批量操作的基类,因此SQLAlchemy的新手用户也可以有效地工作(他们甚至可能不知道SQLAlchemy)。

1 个答案:

答案 0 :(得分:0)

我能够创建这样的类,但不能作为基类,而是mixin:

from sqlalchemy.inspection import inspect
from sqlalchemy import Column, ForeignKey, Integer, Table

class ManyToManyMixin:
    @classmethod
    def __table_cls__(cls, *args, **kwargs):
        return Table(
            *args,
            *[Column(
                '{}_{}'.format(model.__name__.lower(), col.name),
                col.type,
                ForeignKey(col),
                primary_key=True
              ) for model in cls.models for col in inspect(model).primary_key]
            **kwargs
        )

可以用作:

class Family(ManyToManyMixin, CustomBase):
    __tablename__ = 'families'
    other_value = Column(Integer) # just to show that it does not cause any restrictions

    models = (Parent, Child)

您可以找到详细信息here