V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
holinhot
V2EX  ›  问与答

sqlalchemy 中的多对多。如果标签已存在,怎么防止 SQLAlchemy 重复插入标签

  •  
  •   holinhot · 2021-08-24 18:40:49 +08:00 · 821 次点击
    这是一个创建于 1183 天前的主题,其中的信息可能已经有所发展或是发生改变。

    几乎和这个一样。 https://stackoverflow.com/questions/13149829/many-to-many-in-sqlalchemy-preventing-sqlalchemy-from-inserting-into-a-table-if

    看了下答案,一会说是用 upset 。还有说用 unique object (没看懂)

    我建了三个表。文章表,标签表( name 唯一约束),标签文章关系表双主键。这起起来很标准啊,难道不给标签表,name 做唯一约束,这会存很多重复的 Tag 记录,完全没必要。

    还是要自己先查一遍标签是否存在,如果存在怎么调用 SQLAlchemy 来只插入关系记录,而不插入标签。

    def create(db: Session, data: core.schemas.article.Create):
        data.source_images = json.dumps(data.source_images)
        data_dict = data.dict(exclude_unset=True)
        data_dict.pop('tag')
        db_data = schemas.article.Article(**data_dict)
        if data.tag:
            for item in data.tag:
                tag = core.model.article.Article(name=item)
                db_data.article.append(tag)
                
        db.add(db_data)
        db.commit()
        db.refresh(db_data)
        return db_data
    

    这样搞了提交文章时如果标签在标签表已存了 SQLAlchemy 还是会执行插入,但受唯一条件约束而执行失败。

    sqlalchemy.exc.IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "ix_name"
    DETAIL:  Key (name)=(string) already exists.
    
    holinhot
        1
    holinhot  
    OP
       2021-08-24 19:05:49 +08:00
    好像这样可以了
    if data.actress:
    for item in data.actress:
    db_tag = db.query(core.model.actress.Actress).filter(core.model.actress.Actress.name == item).first()
    if not db_tag:
    tag = core.model.actress.Actress(name=item)
    db_data.actress.append(tag)
    else:
    db_data.actress.append(db_tag)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4031 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:25 · PVG 13:25 · LAX 21:25 · JFK 00:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.