如何使用SQLAlchemy将多个类映射到单个表

问题描述 投票:0回答:1

我有一个定义两个对象的域:PropertyAddress。他们有一对一的关系,每个Property都有一个Address

我想有一个表,其中包含PropertyAddress数据,以避免在查询Properties时出现不必要的连接:

create table properties
(
id integer primary key,
name varchar(50) not null,
address_city varchar(50) not null
)

并有波纹管类定义:

class Property(object):
    def __init__(self, id, name, address):
        self.id = id
        self.name = name
        self.address = address

class Address(object):
    def __init__(self, city):
        self.city = city

如何配置SQLAlchemy映射器以支持这种结构? (我看到了继承配置,但它不符合我的情况)

python sqlalchemy
1个回答
3
投票

虽然通常我会投票创建单独的属性和地址关系,但是使用合适的外键约束,您可以使用composite column type将类映射到单个表:

In [2]: class Address:
   ...:     def __init__(self, city):
   ...:         self.city = city
   ...:     def __composite_values__(self):
   ...:         # NOTE: returns a 1-tuple
   ...:         return self.city,
   ...:     def __repr__(self):
   ...:         return "Address(city={!r})".format(self.city)
   ...:     def __eq__(self, other):
   ...:         return isinstance(other, Address) and self.city == other.city
   ...:     def __ne__(self, other):
   ...:         return not self.__eq__(other)

In [3]: class Property(Base):
   ...:     __tablename__ = "properties"
   ...:     id = Column(Integer, primary_key=True)
   ...:     name = Column(Unicode(50), nullable=False)
   ...:     address_city = Column(Unicode(50), nullable=False)
   ...:     address = composite(Address, address_city)
   ...: 
   ...:     def __init__(self, name, address):
   ...:         self.name = name
   ...:         self.address = address

使用上面的类型和模型,您可以创建新属性:

In [5]: session.add(Property('Ye Olde House', Address('London')))

In [6]: session.commit()

和查询:

In [7]: session.query(Property).\
   ...:     filter_by(address=Address('London')).\
   ...:     first()
Out[7]: <__main__.Property at 0x7f02dd8892e8>

In [8]: _.address.city
Out[8]: 'London'

在即将推出的实现PEP 557 – Data Classes的Python 3.7中,Address类可以定义为:

from dataclasses import dataclass, astuple

@dataclass
class Address:
    city: str

    def __composite_values__(self):
        return astuple(self)
© www.soinside.com 2019 - 2024. All rights reserved.