python - sqlalchemy 中的多对多。如果标记已存在,则防止 SQLAlchemy 插入表中

标签 python postgresql orm sqlalchemy many-to-many

我有几个 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 数据库,并且 SQLAlchemy 0.7.9(Python 2.7.3)

我正在考虑作为最后手段的事情:标签在技术上是一个主键,并且 没有别的,我可以只用一个 task_id->tag 表而没有标签 table 。但我希望能够将元数据附加到标签本身 必要时上路。

最佳答案

对于“仅限唯一标签”配方,我通常使用唯一对象配方,或者它的一些变体:http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject .

这自然需要对特定行进行 SELECT 以判断它是否首先存在。 ORM 目前不直接支持“upsert”技术,它使用特定于数据库的命令根据数据库端的确定来插入或更新行。无论如何,您使用的是 Postgresql,它实际上不支持任何 native “upsert”功能,除了一个使用公用表表达式的非常笨拙的系统。

关于python - sqlalchemy 中的多对多。如果标记已存在,则防止 SQLAlchemy 插入表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13149829/

相关文章:

python - 给定日期后的 DatetimeField 过滤器

python - 模块 'pickle' 没有属性 'dump'

c - Postgres C 扩展集合 : How to detect first time aggregate function is called

arrays - postgres 中的 Array_agg 有选择地引用

python - 如何从 Django 中的错误电子邮件中删除敏感信息

python - 如何强制 genfromtxt 读取 csv 作为记录数组?

sql - 按顺序更新列值,其中新值基于 'previous' 行中的更新值

hibernate - hibernate -如何与孤儿一起保存 parent

java - 在 Hibernate 中执行 Criteria 查询后是否需要提交/关闭 session ?

php - 如何选择 ORM