我有一些 ORM 映射表,它们(缩减)如下所示:
class Tag(Base):
__tablename__ = 'tags'
tag_name = Column(String, primary_key=True)
task2tag_assoc = Table('tasktags', Base.metadata,
Column('task_id', UUID, ForeignKey('tasks.task_id', ondelete='cascade'),
primary_key=True),
Column('tag_name', String, ForeignKey('tags.tag_name', ondelete='cascade'),
primary_key=True)
)
class Task(Base):
__tablename__ = 'tasks'
task_id = Column(UUID, primary_key=True)
_tags = relationship('Tag', secondary=task2tag_assoc, backref='tasks',
collection_class=set)
tags = association_proxy('_tags', 'tag_name')
def __init__(self, task_id, tags):
self.task_id = task_id
self.tags = set([tags])
通过这个设置,我可以创建一个带有新标签的任务就好了。它在表中创建标记行tags
,然后在表中创建与新任务的关联tasktags
。
t = Task(task_id = uuid4(), tags=['foo', 'bar']) #this works
当我尝试使用tags
表中已存在的标签创建任务时,问题就来了。
t2 = Task(task_oid = uuid4(), tags=['foo', 'baz']) #this will give an integrity error
似乎 SQLAlchemy总是尝试将标签插入到标签表中,无论它是否已经存在。如果标签已经存在,我真的希望它只创建关联。这似乎在多对多情况下是相当正常的,但我在文档中找不到任何地方显示我可能做错了什么。
有没有办法得到我想要的行为?
作为背景,我正在使用带有 psycopg2 驱动程序的 postgresql 9.1 DB 和 SQLAlchemy 0.7.9 (Python 2.7.3)
我正在考虑作为最后手段的事情:标签在技术上是一个主键,没有别的,我可以只使用一个 task_id->tag 表而没有标签表。但如果有必要,我希望能够将元数据附加到标签本身。