Как выполнить обновление с помощью SqlAlchemy?

У меня есть запись, которую я хочу сохранить в базе данных, если ее нет, и если она уже есть (первичный ключ существует), я хочу, чтобы поля были обновлены до текущего государственный. Это часто называют upsert .

Следующий неполный фрагмент кода демонстрирует, что будет работать, но он кажется чрезмерно неуклюжим (особенно, если столбцов было намного больше). Какой способ лучше / лучше?

Base = declarative_base()
class Template(Base):
    __tablename__ = 'templates'
    id = Column(Integer, primary_key = True)
    name = Column(String(80), unique = True, index = True)
    template = Column(String(80), unique = True)
    description = Column(String(200))
    def __init__(self, Name, Template, Desc):
        self.name = Name
        self.template = Template
        self.description = Desc

def UpsertDefaultTemplate():
    sess = Session()
    desired_default = Template("default", "AABBCC", "This is the default template")
    try:
        q = sess.query(Template).filter_by(name = desiredDefault.name)
        existing_default = q.one()
    except sqlalchemy.orm.exc.NoResultFound:
        #default does not exist yet, so add it...
        sess.add(desired_default)
    else:
        #default already exists.  Make sure the values are what we want...
        assert isinstance(existing_default, Template)
        existing_default.name = desired_default.name
        existing_default.template = desired_default.template
        existing_default.description = desired_default.description
    sess.flush()

Есть ли лучший или менее подробный способ сделать это? Что-то вроде этого было бы здорово:

sess.upsert_this(desired_default, unique_key = "name")

хотя unique_key kwarg, очевидно, не нужен (ORM должна легко это понять), я добавил его только потому, что SQLAlchemy имеет тенденцию работать только с первичным ключом. например: Я искал, применимо ли Session.merge , но это работает только с первичным ключом, который в данном случае является автоматически увеличивающимся идентификатором, который не очень полезен для этой цели.

Пример использования для этого - просто запуск серверного приложения, которое могло обновить свои ожидаемые данные по умолчанию. то есть: никаких проблем с параллелизмом для этого апсерта.

53
задан competent_tech 25 December 2011 в 12:14
поделиться