Обновление SQLAlchemy, если существует уникальный ключ - PullRequest
16 голосов
/ 28 марта 2012

У меня есть класс:

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 кажется более ясным - возможно, удерживает меня от операции по дробовику.

Как мне туда добраться? Я довольно новичок в Python и SQLAlchemy, поэтому любые дополнительные мысли по поводу моего кода будут оценены.

Спасибо.

P.S. SQLAlchemy ТАК Гигантский, и они не предоставляют удобный способ сделать INSERT ... ON DUPLICATE KEY UPDATE, а? WOW!

Ответы [ 2 ]

10 голосов
/ 29 марта 2012

Вы можете попробовать это

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

9 голосов
/ 12 июля 2017

От версии 1.2 SQLAlchemy будет поддерживать on_duplicate_key_update для MySQL

Также есть примеров того, какчтобы использовать его:

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_update для PostgreSQL

Примеры :

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)
...