我有两种模式:
class Person(Model):
id
name
skills = relationship(Skill)
class Skill(Model):
id
skill
person_id
一开始,例如:
jack = Person(name='jack')
jack.skills = [Skill(s) for s in ['python', 'ruby']]
jack.save()
然后,有一天,杰克失去了他的技能'红宝石'但赢得了'迅速' 所以他的技能是['python','swift']。
我目前的更新方式是:
old = ['python', 'ruby']
new = ['python', 'swift']
set(old), set(new)
unchanged = old.intersection(new)
,所以我获得了不会改变的技能set(new - unchanged)
set(old-unchanged)
有更简单的方法吗?
答案 0 :(得分:0)
在关系上使用collection_class=set
将其视为集合而不是列表。
以下是如何将人与技能联系起来的实例。这是一个多对多的关系,而不是每个技能与一个person_id相关,每个技能可以通过person_skill表与许多人相关。关系集合是set
,并且Skill具有__hash__
函数,可以使相同名称的技能散列相同。
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base(bind=engine)
Session = sessionmaker(bind=engine)
session = Session()
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, unique=True)
# many-to-many relation, as a set
skills = relationship('Skill', 'person_skill', collection_class=set)
class Skill(Base):
__tablename__ = 'skill'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, unique=True)
def __hash__(self):
# so that the set collection will handle duplicate entries
return hash((self.__class__, self.name))
# many-to-many table, relate a person to a skill
person_skill = Table(
'person_skill', Base.metadata,
Column('person_id', Integer, ForeignKey(Person.id), primary_key=True),
Column('skill_id', Integer, ForeignKey(Skill.id), primary_key=True)
)
# create the tables
Base.metadata.create_all()
# populate some skills and people
s1 = Skill(name='python')
s2 = Skill(name='sqlalchemy')
s3 = Skill(name='questions')
s4 = Skill(name='ruby')
p1 = Person(name='davidism', skills={s1, s2, s4})
p2 = Person(name='user2653947', skills={s3})
session.add_all([p1, p2])
session.commit()
# change some skills on people
p1.skills.discard(s4)
p2.skills.add(s2)
session.commit()
这不是一个完整的解决方案。例如,您可以插入the unique object pattern demonstrated in this answer以确保您创建的技能永远不会重复。