SQLAlchemy是否与Django的get_或_create等效?

2024-05-09 01:44:25 发布

您现在位置:Python中文网/ 问答频道 /正文

如果对象已经存在(基于提供的参数),我想从数据库中获取它;如果不存在,我想创建它。

Django的^{}(或source)做到了这一点。在SQLAlchemy中是否有等效的快捷方式?

我现在是这样写出来的:

def get_or_create_instrument(session, serial_number):
    instrument = session.query(Instrument).filter_by(serial_number=serial_number).first()
    if instrument:
        return instrument
    else:
        instrument = Instrument(serial_number)
        session.add(instrument)
        return instrument

Tags: 对象django数据库numbersource参数getreturn
3条回答

遵循@WoLpH的解决方案,这是对我有效的代码(简单版本):

def get_or_create(session, model, **kwargs):
    instance = session.query(model).filter_by(**kwargs).first()
    if instance:
        return instance
    else:
        instance = model(**kwargs)
        session.add(instance)
        session.commit()
        return instance

有了这个,我可以让你或你创建我的模型的任何对象。

假设我的模型对象是:

class Country(Base):
    __tablename__ = 'countries'
    id = Column(Integer, primary_key=True)
    name = Column(String, unique=True)

要获取或创建对象,我会编写:

myCountry = get_or_create(session, Country, name=countryName)

我一直在处理这个问题,最后得到了一个相当可靠的解决方案:

def get_one_or_create(session,
                      model,
                      create_method='',
                      create_method_kwargs=None,
                      **kwargs):
    try:
        return session.query(model).filter_by(**kwargs).one(), False
    except NoResultFound:
        kwargs.update(create_method_kwargs or {})
        created = getattr(model, create_method, model)(**kwargs)
        try:
            session.add(created)
            session.flush()
            return created, True
        except IntegrityError:
            session.rollback()
            return session.query(model).filter_by(**kwargs).one(), False

我只是在所有细节上写了一个fairly expansive blog post,但是有一些关于我为什么使用这个的想法。

  1. 它解包成一个元组,告诉您对象是否存在。这在您的工作流程中通常很有用。

  2. 该函数提供了使用@classmethod修饰的creator函数(以及特定的属性)的能力。

  3. 当有多个进程连接到数据存储时,该解决方案可防止竞争条件。

编辑:我已将session.commit()更改为session.flush(),如this blog post中所述。注意,这些决定是特定于所使用的数据存储的(在本例中是Postgres)。

编辑2:我在函数中使用{}作为默认值进行了更新,因为这是典型的Python gotcha。谢谢你the comment,奈杰尔!如果你对此感到好奇,请查看this StackOverflow questionthis blog post

基本上就是这样,没有捷径可走。

当然,你们可以概括为:

def get_or_create(session, model, defaults=None, **kwargs):
    instance = session.query(model).filter_by(**kwargs).first()
    if instance:
        return instance, False
    else:
        params = dict((k, v) for k, v in kwargs.iteritems() if not isinstance(v, ClauseElement))
        params.update(defaults or {})
        instance = model(**params)
        session.add(instance)
        return instance, True

相关问题 更多 >