我将一堆专利数据存储在MySQL数据库中,并通过SQLAlchemy与它进行交互。我在专利类中有一个代表受让人名单(被指定专利的公司)的集合:
assignees = relationship('Company', secondary=patent_company_table, backref='patents')
我正在处理存储在数据库中的一些对象和专利对象p
,我想从a
的受让人中删除一些受让人p
(公司对象)名单。基于http://docs.sqlalchemy.org/en/latest/orm/session.html#deleting-from-collections,似乎调用s.delete(a)
实际上会删除公司对象a
。我只是想从a
的受让人列表中删除受让人p
(即删除patent_company_table中的一行),而不是实际删除公司对象,因为a
可能在另一个专利中对象的受让人名单。
我尝试创建一个新列表new_assignees
,除p
之外只包括来自a
的受让人,然后调用:
p.assignees = new_assignees
s.add(p)
遗憾的是,这实际上并没有将p
标记为脏,因此我认为它不会影响数据库。
对于如何从集合中删除对象,删除patent_company_table中的行而不是从Company表中删除对象,您有什么建议吗?
谢谢。
以下是代码片段:
assignees = patent.assignees
for assignee in assignees:
if assignee in duplicate_company_to_default:
patent.assignees.remove(assignee)
default_company = duplicate_company_to_default[assignee]
if default_company not in assignees:
added_patent_count += 1
patent.assignees.append(default_company)
循环完所有专利后,added_patent_count = 983672
但session.dirty()
中没有任何对象。通过append
或remove
?
答案 0 :(得分:8)
SQLAlchemy集合支持类似列表的追加/删除操作。
p.assignees.remove(c)
这应删除c
表单p.assignees
而不从数据库中删除c
。
答案 1 :(得分:7)
一个工作示例脚本意味着,我们可以完全运行它。这是从您提供的片段生成的脚本。有一点有用的是将“受让人”评估为一个列表,因为你要删除它,很可能你没有正确迭代。
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base= declarative_base()
patent_company_table = Table('pct', Base.metadata,
Column('patent_id', Integer, ForeignKey('patent.id')),
Column('company_id', Integer, ForeignKey('company.id'))
)
class Patent(Base):
__tablename__ = "patent"
id = Column(Integer, primary_key=True)
assignees = relationship('Company', secondary=patent_company_table, backref='patents')
class Company(Base):
__tablename__ = "company"
id = Column(Integer, primary_key=True)
e = create_engine("sqlite://")
Base.metadata.create_all(e)
s = Session(e)
p = Patent()
c1, c2, c3, c4, c5 = Company(), Company(), Company(), Company(), Company()
d1, d2 = Company(), Company()
duplicate_company_to_default = {c1:d1, c2:d2, c3:d1, c4:d2}
new_assignees = [c1, c2, c3, c4, c5]
p.assignees = new_assignees
s.add(p)
s.commit()
patent = s.query(Patent).first()
assignees = patent.assignees
added_patent_count = 0
for assignee in list(assignees):
if assignee in duplicate_company_to_default:
patent.assignees.remove(assignee)
default_company = duplicate_company_to_default[assignee]
if default_company not in assignees:
added_patent_count += 1
patent.assignees.append(default_company)
assert p in s.dirty
s.commit()
assert set(p.assignees) == set([d1, d2, c5])