SQLAlchemy的更新,如果唯一的密钥存在

问题描述:

我有一个类:SQLAlchemy的更新,如果唯一的密钥存在

class Tag(Base, TimestampMixin): 
    """Tags""" 
    __tablename__ = 'tags' 
    __table_args__ = {'mysql_engine' : 'InnoDB', 'mysql_charset' : 'utf8' } 

    id = Column(Integer(11), autoincrement = True, primary_key = True) 
    tag = Column(String(32), nullable = False, unique = True) 
    cnt = Column(Integer(11), index = True, nullable = False, default = 1) 

    def __init__(self, tag): 
     t = session.query(Tag).filter_by(tag=tag).first() 
     if t: 
      self.cnt = t.cnt+1 
      self.tag = t.tag 
     else: 
      self.tag = tag 

    def __repr__(self): 
     return "<Tag('%s')>" % (self.tag,) 

    def __unicode__(self): 
     return "%s" % (self.tag,) 

当添加标签:

tag = Tag('tag') 
session.add(tag) 
session.commit() 

我想它来更新现有tag

当然,我可能已经做到了这一点:

tag = session.query(Tag).filter_by(tag='tag').first() 
if tag: 
    tag.cnt++ 
else: 
    tag = Tag('tag') 
session.add(tag) 
session.commit() 

,但在Tag类保持这样的逻辑似乎是更加清晰 - 有可能让我离开猎枪手术。

我该如何到达那里? 我对PythonSQLAlchemy很新,所以对我的代码的任何额外想法将不胜感激。

谢谢。

P.S. SQLAlchemy是SO GIGANTIC,他们不提供一个方便的方法来做INSERT ... ON DUPLICATE KEY UPDATE,是吧?哇!

+2

尝试session.me rge(标签)而不是session.add(标签) – 2012-03-30 17:41:50

你可以试试这个

def get_or_increase_tag(tag_name): 
    tag = session.query(Tag).filter_by(tag=tag_name).first() 
    if not tag: 
     tag = Tag(tag_name) 
    else: 
     tag.cnt += 1 
    return tag 

您可以查看链接https://stackoverflow.com/search?q=Insert+on+duplicate+update+sqlalchemy

1.2版 SQLAlchemy的支持on_duplicate_key_updateMySQL的

还有如何使用examples它:

from sqlalchemy.dialects.mysql import insert 

insert_stmt = insert(my_table).values(
    id='some_existing_id', 
    data='inserted value') 

on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
    data=insert_stmt.values.data, 
    status='U' 
) 

conn.execute(on_duplicate_key_stmt) 

从版本1.1 SQLAlchemy的支持on_conflict_do_updatePostgreSQL的

Examples

from sqlalchemy.dialects.postgresql import insert 

insert_stmt = insert(my_table).values(
    id='some_existing_id', 
    data='inserted value') 

do_update_stmt = insert_stmt.on_conflict_do_update(
    constraint='pk_my_table', 
    set_=dict(data='updated value') 
) 

conn.execute(do_update_stmt)