如何在sqlalchemy上映射一对多关系
How to map one-to-many relationship on sqlalchemy
我正在学习 flask+sqlalchemy,但我在使用 ORM 时遇到了一些问题。我有一个 model.py 有一个 class House
和一个 class Member
.
class House:
def __init__(self, members: typing.Set['Member'] = None) -> None:
if not patients:
self.member = set()
else:
self.member = set(member)
def add_member(self, person: 'Patient'):
self.patients.add(person)
def remove_member(self, patient: 'Member'):
self.member.remove(patient)
class Member:
def __init__(self, first_name: str, email: str, phone: str, age: int, gender: str, last_name=None) -> None:
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone = phone
self.age = age
self.gender = gender
def __hash__(self) -> int:
return hash(self.email)
def __eq__(self, other):
if isinstance(other, Patient):
return self.email == other.email
return NotImplemented
在 orm.py
我有:
house = Table(
'house', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True)
)
member = Table(
'patient', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True),
Column('first_name', String(255)),
Column('last_name', String(255)),
Column('email', String(255)),
Column('phone', String(255)),
Column('age', INTEGER),
Column('gender', String(255)),
member_allocation = Table(
'patient_allocation', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True),
Column('member_id', ForeignKey('member.id')),
Column('house_id', ForeignKey('house.id')),
)
def start_mappers():
member_mapper = mapper(model.Member,member)
house_mapper = mapper(
model.House,
house,
properties={
'members': relationship(
member_mapper,
secondary=member_allocation,
collection_class=set,
backref=backref('house')),
})
一个房子可以有很多成员,一个成员只能有一个房子。我觉得我不需要 member_allocation table。我觉得很简单,在 member
table 上有一个 house_id
作为外键('house.id')就足够了,而且 member_mapper
必须是这样的:
member_mapper = mapper(
model.Member,
member,
properties={'house': relationship(house_mapper)
})
但如果我理解正确,properties
字典中的键(上面代码中的 house
)必须是映射的 class 的属性。在我的例子中 house
不是 member
class.
的属性
我哪里错了?
backref 属性 members
和 house
都应由 SQLAlchemy 创建和填充。
你说得对,如果每个成员只能拥有一个房子,那么你就不需要协会 table(因为它是 one2many)。对于 many2many,您需要 table。您应该可以这样做(将 house_id
列移至成员 table):
def start_mappers():
member_mapper = mapper(model.Member,member)
house_mapper = mapper(model.House,
house,
properties={
'members': relationship(
member_mapper,
collection_class=set,
backref=backref('house')),
})
我正在学习 flask+sqlalchemy,但我在使用 ORM 时遇到了一些问题。我有一个 model.py 有一个 class House
和一个 class Member
.
class House:
def __init__(self, members: typing.Set['Member'] = None) -> None:
if not patients:
self.member = set()
else:
self.member = set(member)
def add_member(self, person: 'Patient'):
self.patients.add(person)
def remove_member(self, patient: 'Member'):
self.member.remove(patient)
class Member:
def __init__(self, first_name: str, email: str, phone: str, age: int, gender: str, last_name=None) -> None:
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone = phone
self.age = age
self.gender = gender
def __hash__(self) -> int:
return hash(self.email)
def __eq__(self, other):
if isinstance(other, Patient):
return self.email == other.email
return NotImplemented
在 orm.py
我有:
house = Table(
'house', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True)
)
member = Table(
'patient', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True),
Column('first_name', String(255)),
Column('last_name', String(255)),
Column('email', String(255)),
Column('phone', String(255)),
Column('age', INTEGER),
Column('gender', String(255)),
member_allocation = Table(
'patient_allocation', metadata,
Column('id', INTEGER, primary_key=True, autoincrement=True),
Column('member_id', ForeignKey('member.id')),
Column('house_id', ForeignKey('house.id')),
)
def start_mappers():
member_mapper = mapper(model.Member,member)
house_mapper = mapper(
model.House,
house,
properties={
'members': relationship(
member_mapper,
secondary=member_allocation,
collection_class=set,
backref=backref('house')),
})
一个房子可以有很多成员,一个成员只能有一个房子。我觉得我不需要 member_allocation table。我觉得很简单,在 member
table 上有一个 house_id
作为外键('house.id')就足够了,而且 member_mapper
必须是这样的:
member_mapper = mapper(
model.Member,
member,
properties={'house': relationship(house_mapper)
})
但如果我理解正确,properties
字典中的键(上面代码中的 house
)必须是映射的 class 的属性。在我的例子中 house
不是 member
class.
我哪里错了?
backref 属性 members
和 house
都应由 SQLAlchemy 创建和填充。
你说得对,如果每个成员只能拥有一个房子,那么你就不需要协会 table(因为它是 one2many)。对于 many2many,您需要 table。您应该可以这样做(将 house_id
列移至成员 table):
def start_mappers():
member_mapper = mapper(model.Member,member)
house_mapper = mapper(model.House,
house,
properties={
'members': relationship(
member_mapper,
collection_class=set,
backref=backref('house')),
})