简体   繁体   English

在SQLAlchemy中禁用提交对象更改

[英]Disabling committing object changes in SQLAlchemy

I'm using SQLAlchemy in project that is not a web application. 我在不是Web应用程序的项目中使用SQLAlchemy。 It is a server application that loads number of different objects from database and modifies them locally, but don't want to save those updates to the database each time a commit is issued. 它是一个服务器应用程序,它从数据库加载许多不同的对象并在本地修改它们,但是每次发出提交时都不希望将这些更新保存到数据库中。 I was previously working with Django ORM for some web projects and found it better suited for what I'm trying to achieve. 我以前和Django ORM合作过一些网络项目,发现它更适合我想要实现的目标。 In Django ORM I could .save() each object whenever I wanted without saving other things I may not want to save. 在Django ORM中我可以随时随地使用.save()每个对象而不保存其他我可能不想保存的东西。 I understand why it works like this in SQLAlchemy, but I wonder how I could do this in the Django-like way? 我理解为什么它在SQLAlchemy中的工作方式如此,但我想知道如何以类似Django的方式做到这一点?


Update: To make it easier to understand what I'm trying to achieve, I'll provide you an example. 更新:为了更容易理解我想要实现的目标,我将为您提供一个示例。

This is how it works actually: 这是它实际工作的方式:

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

This is how I want it to work: 这就是我希望它的工作方式:

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

I want to have greater control of what is actually saved. 我想更好地控制实际保存的内容。 I want to save changes of each object every 5 minute or so. 我想每5分钟左右保存每个对象的更改。

I use something like: 我使用类似的东西:

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

and then I define my models as: 然后我将我的模型定义为:

class User(db.Model, BaseModel)

So, now I can do: 那么,现在我可以这样做:

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

This is what you were planning to achieve ? 这是你打算实现的目标?

I am not sure i understand your predicament. 我不确定我理解你的困境。

In Django, 在Django,

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

or alternatively 或者

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

In SQLAlchemy, 在SQLAlchemy中,

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

At this point you have only added the object to the session and it has not yet committed the transaction. 此时,您只将对象添加到会话中,并且尚未提交事务。 You need to commit only after you have done whatever changes were required 只有在完成所需的任何更改后才需要提交

session.commit()

take a look that this link . 看看这个链接 I think it will make the transition from Django ORM to SqlAlchemy easier. 我认为它将使从Django ORM到SqlAlchemy的过渡更容易。

UPDATE UPDATE

For such a situation, you could use multiple sessions. 对于这种情况,您可以使用多个会话。

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)

Created a table 'users' in the 'test' db. 在'test'db中创建了一个表'users'。 Also, 2 session objects, session1 and session2, have been initialized. 此外,已初始化2个会话对象session1和session2。

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

The table users will now have 2 records 表用户现在将有2条记录

1: foo, 10
2: bar, 20

Fetching the 'foo' record sing session1 and 'bar' using session2. 使用session2获取'foo'记录会话session1和'bar'。

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

Making changes to the 2 records 更改2条记录

foo.age = 11
bar.age = 21

Now, if you want the changes of foo alone to carry over, 现在,如果你想让foo的变化继续进行,

session1.commit()

and for bar, 而对于酒吧,

session2.commit() 

Not to stir up an old post, but 不要挑起旧职位,但是

You say: 你说:

I want to save changes of each object every 5 minute or so. 我想每5分钟左右保存每个对象的更改。

So why not use a scheduler like Celery .(I use pyramid_celery ) 那么为什么不使用像Celery这样的调度程序。(我使用pyramid_celery

With this you can save each object every 5 minutes, ie You can add a decorator: 有了这个,您可以每5分钟保存一个对象,即您可以添加一个装饰器:

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

This works great, especially when you need to update your database to make sure it is up to date(in the case that there is many users using your system) 这非常有用,尤其是当您需要更新数据库以确保它是最新的时(如果有许多用户使用您的系统)

Hope this helps someone with the, saving every 5 minutes part. 希望这可以帮助有人, 每5分钟节省一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM