8

我在不是 Web 应用程序的项目中使用 SQLAlchemy。它是一个服务器应用程序,它从数据库加载许多不同的对象并在本地修改它们,但不希望每次提交时都将这些更新保存到数据库中。我以前在一些 Web 项目中使用 Django ORM,发现它更适合我想要实现的目标。在 Django ORM 中,我可以随时 .save() 每个对象,而无需保存我可能不想保存的其他内容。我理解为什么它在 SQLAlchemy 中这样工作,但我想知道如何以类似 Django 的方式做到这一点?


更新: 为了更容易理解我想要实现的目标,我将为您提供一个示例。

它实际上是这样工作的:

a = MyModel.query.get(1)
b = MyModel.query.get(1)

a.somefield = 1
b.somefield = 2

# this will save both of changed models
session.commit()

这就是我希望它的工作方式:

a = MyModel.query.get(1)
b = MyModel.query.get(1)

a.somefield = 1
b.somefield = 2

a.save()
# I didn't want to save b, changes of b weren't committed

我想更好地控制实际保存的内容。我想每 5 分钟左右保存每个对象的更改。

4

3 回答 3

4

我使用类似的东西:

class BaseModel(object):
    def save(self, commit=True):
        # this part can be optimized.
        try:
            db.session.add(self)
        except FlushError:
            # In case of an update operation.
            pass

        if commit:
            db.session.commit()

    def delete(self, commit=True):
        db.session.delete(self)

        if commit:
            db.session.commit()

然后我将我的模型定义为:

class User(db.Model, BaseModel)

所以,现在我可以这样做:

u = User(username='foo', password='bar')
u.save()

这就是您计划实现的目标?

于 2012-11-27T06:27:40.933 回答
2

我不确定我是否理解你的困境。

在 Django 中,

foo = MyModel(field1='value1', field2='value2')
foo.save()

或者

foo = MyModel.objects.create(field1='value1', field2='value2')

在 SQLAlchemy 中,

foo = MyModel(field1='value1', field2='value2')
session.add(foo)

此时您只是将对象添加到会话中,它还没有提交事务。只有在完成所需的任何更改后,您才需要提交

session.commit()

看看这个链接。我认为这将使从 Django ORM 到 SqlAlchemy 的过渡更容易。

更新

对于这种情况,您可以使用多个会话。

engine = create_engine("postgresql+psycopg2://user:password@localhost/test")
metadata = MetaData(bind=engine)
Session = sessionmaker(bind=engine)
session1 = Session()
session2 = Session()
Base = declarative_base()
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    age = Column(Integer)
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        return "<User('%s','%s')>" % (self.name, self.age)
Base.metadata.create_all(engine)

在“测试”数据库中创建了一个表“用户”。此外,还初始化了 2 个会话对象 session1 和 session2。

a = User('foo','10')
b = User('bar', '20')
session1.add(a)
session1.add(b)
session1.commit()

表用户现在将有 2 条记录

1: foo, 10
2: bar, 20

使用 session2 获取 'foo' 记录唱 session1 和 'bar'。

foo = session1.query(User).filter(User.name == "foo").first()
bar = session2.query(User).filter(User.name == "bar").first()

更改 2 条记录

foo.age = 11
bar.age = 21

现在,如果您希望仅 foo 的更改继续进行,

session1.commit()

对于酒吧,

session2.commit() 
于 2012-07-25T11:14:24.510 回答
0

不是为了挑起旧帖,而是

你说:

我想每 5 分钟左右保存每个对象的更改。

那么为什么不使用像Celery这样的调度程序。(我使用pyramid_celery

有了这个,您可以每 5 分钟保存一次每个对象,即您可以添加一个装饰器:

@periodic_task(run_every=crontab(minute="*/5")
def somefunction():
    #your code here

这很好用,尤其是当您需要更新数据库以确保它是最新的时(在有很多用户使用您的系统的情况下)

希望这可以帮助某人,每 5 分钟节省一次

于 2014-02-24T14:56:49.927 回答