在 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。
有什么想法吗?
在第一个示例中,您在 Hotel
和 Apartment
table 中有 person_id
列,这意味着您将在 Hotel
或每个人 Apartment
tables,这似乎不是您打算做的。所以应该把外键移到Person
table。
所以下一个问题是对两个 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
.
来检查此人链接到的住宿类型
我是初学者 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。
有什么想法吗?
在第一个示例中,您在 Hotel
和 Apartment
table 中有 person_id
列,这意味着您将在 Hotel
或每个人 Apartment
tables,这似乎不是您打算做的。所以应该把外键移到Person
table。
所以下一个问题是对两个 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
.