在 SQLAlchemy 中有效地处理一对多关系

Working with an One-to-many relationship in SQLAlchemy efficient way

我是初学者 SQL 用户。

我有一个数据库,其中包含三个 table、table 个人以及 table 旅馆和公寓。每个人与一间酒店或公寓只有一种关系,但每个酒店或公寓可以分配一个或多个人。

具有以下架构:

class Person(Base):
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True, nullable=False)
    person_name = Column(String, nullable=False)
    status = Column(String, nullable=False) 

class Hotel(Base):
    __tablename__ = 'hotel'
    id = Column(Integer, primary_key=True, nullable=False)
    hotel_name = Column(String, nullable=False)
    hotel_address = Column(String)

    person_id = Column(Integer, ForeignKey("person.id"), nullable=False)
    person = relationship("Person", backref=backref("hotel", uselist=False))

class Apartment(Base):
    __tablename__ = 'apartment'
    id = Column(Integer, primary_key=True, nullable=False)
    apartment_address = Column(String, nullable=False)

    person_id = Column(Integer, ForeignKey("person.id"), nullable=False)
    person = relationship("Person", backref=backref("apartment", uselist=False))

或者这一个,其中每家酒店和公寓都有一个唯一的密钥,并过滤新的 "key" 列:

class Person(Base):
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True, nullable=False)
    person_name = Column(String, nullable=False)
    status = Column(String, nullable=False) 
    key = Column(String, nullable=False) 

class Hotel(Base):
    __tablename__ = 'hotel'
    id = Column(Integer, primary_key=True, nullable=False)
    hotel_name = Column(String, nullable=False)
    hotel_address = Column(String)
    key = Column(String, nullable=False, unique=True)

class Apartment(Base):
    __tablename__ = 'apartment'
    id = Column(Integer, primary_key=True, nullable=False)
    apartment_address = Column(String, nullable=False)
    key = Column(String, nullable=False, unique=True)

当具有唯一键时,酒店和公寓 table 中的列 "id" 是否不必要?

第二个问题,关于Person中的这一栏table:

status = Column(String, nullable=False) 

我希望状态列只是(酒店、公寓)中的值之一,它可以告诉您在酒店或公寓中确切查找关系的位置 table。

有什么想法吗?

在第一个示例中,您在 HotelApartment table 中有 person_id 列,这意味着您将在 Hotel 或每个人 Apartment tables,这似乎不是您打算做的。所以应该把外键移到Persontable。 所以下一个问题是对两个 table 都使用一个外键,这样你就不必进行繁琐的检查(比如在设置 apartment_id 时检查是否设置了 hotel_id) .这可以使用 SqlAlchemy 的 polymorphic_identity 来完成。你可以阅读它 here。在这种情况下,您的模型结构应该如下所示:

class Person(Base):
        __tablename__ = 'person'
        id = Column(Integer, primary_key=True, nullable=False)
        person_name = Column(String, nullable=False)

        accommodation_id = Column(Integer, ForeignKey("accommodation.id"))
        accommodation = relationship("Accommodation", backref="people")


class Accommodation(Base):
    __tablename__ = 'accommodation'
    __mapper_args__ = {
        'polymorphic_identity':'accommodation',
        # polymorphic_on determines the field that will have values like 'hotel' and 'apartment' depending on the table
        'polymorphic_on': 'accommodation_type'
    }

    id = Column(Integer, primary_key=True)
    accommodation_type = Column(String(32))
    address = Column(String)


class Hotel(Accommodation):
        __tablename__ = 'hotel'
        __mapper_args__ = {
            # all the records in this table will have accommodation_type = 'hotel'
            'polymorphic_identity': 'hotel'
        }

        id = Column(Integer, ForeignKey('accommodation.id'), primary_key=True)
        hotel_name = Column(String, nullable=False)


class Apartment(Accommodation):
        __tablename__ = 'apartment'
        __mapper_args__ = {
            # all the records in this table will have accommodation_type = 'apartment'
            'polymorphic_identity': 'apartment'
        }

        id = Column(Integer, ForeignKey('accommodation.id'), primary_key=True)

这样,您就有了基础模型 Accommodation,它的 id 链接到 table 和 Hotel 和 [=22] 中的 id 列=],其中仅包含特定于它们的字段。 person.accommodation 将 return 为酒店或公寓,具体取决于实际值,并且 parent 和 child table 的所有属性都将可用。这样您就可以确保一个人不会同时链接到酒店和公寓。您可以通过检查 person.accommodation.accommodation_type.

来检查此人链接到的住宿类型