最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

[已解决]SQLAlchemy中如何得到db.session.commit后的新增的对象

Flask crifan 10063浏览 0评论

折腾:

[记录]Flask中给活动到期添加提醒功能

期间,对于已有的代码:

/Users/crifan/dev/dev_root/daryun/SIPEvents/sourcecode/sipevents/sipevents/models.py

class Event(db.Model):
    __tablename__ = “events”
    # Columns
    id = db.Column(db.Integer, primary_key = True, autoincrement = True, nullable=False)
    #user_openid = db.Column(db.String(64))
    #user_openid = db.Column(db.String(64), db.ForeignKey(‘user.openid’))
    user_openid = db.Column(db.String(64), db.ForeignKey(‘wechat_users.openid’))
    title = db.Column(db.String(128))
    start_date = db.Column(db.DateTime)
    end_date = db.Column(db.DateTime)
    location = db.Column(db.String(256))
    cur_user_num = db.Column(db.Integer)
    max_user_num = db.Column(db.Integer)
    is_public = db.Column(db.Boolean)
    description = db.Column(db.Text)
    notification_time = db.Column(db.Enum(NotificationTime))
    # joiners = db.relationship(‘EventJoiner’, backref=’user’, lazy=’dynamic’)
    #joiners = db.relationship(‘User’, secondary = event_joiners, backref=’events’)
    #joiners = db.relationship(‘User’, secondary=event_joiners, backref=’joined_events’,lazy=’dynamic’)
    joiners = db.relationship(‘User’, secondary=event_joiners, backref=’joined_events’)
    def __init__(self,
                 # id,
                 user_openid,
                 title = “”,
                 location = “”,
                 start_date = None,
                 end_date = None,
                 cur_user_num = 0,
                 max_user_num = 0,
                 is_public = False,
                 description = “”,
                 notification_time = NotificationTime.NotNotify):
        # self.id = id
        self.user_openid = user_openid
        self.title = title
        self.location = location
        self.start_date = start_date
        self.end_date = end_date
        self.cur_user_num = cur_user_num
        self.max_user_num = max_user_num
        self.is_public = is_public
        self.description = description
        self.notification_time = notification_time
    def __repr__(self):
        #return u'<Event id=%d user_openid=%s title=%r>’ % (self.id, self.user_openid, self.title)
        return u'<Event id=%s user_openid=%s title=%r>’ % (self.id, self.user_openid, self.title)

/Users/crifan/dev/dev_root/daryun/SIPEvents/sourcecode/sipevents/sipevents/views.py

        newEvent = Event(user_openid = curUser.openid,
                         title = title,
                         location = location,
                         start_date = startDate,
                         end_date = endDate,
                         cur_user_num = 1,
                         max_user_num = maxUserNum,
                         is_public = is_public,
                         description = description,
                         notification_time = notificationTimeEnum)
        gLog.debug(‘newEvent=%s’, newEvent)
        #add self to joiners
        gLog.debug(“type(curUser)=%s, curUser=%s”, curUser, type(curUser))
        newEvent.joiners.append(curUser)
        gLog.debug(‘added self to joiners, newEvent=%s’, newEvent)
        db.session.add(newEvent)
        db.session.commit()
        gLog.debug(“added new event=%s”, newEvent)

希望实现:

db.session.add(newEvent)

以及:

db.session.commit()

之后,可以得到对应的这个新的event的对象

注:此处的newEvent变量,是提交之前的,其id是为空的

sqlalchemy get object after commit

python – sqlalchemy flush() and get inserted id? – Stack Overflow

        db.session.add(newEvent)
        db.session.refresh(newEvent)
        db.session.commit()

搜:

sqlalchemy  session refresh flush

Session API — SQLAlchemy 1.1 Documentation

flush(objects=None)

Flush all the object changes to the database.

Writes out all pending object creations, deletions and modifications to the database as INSERTs, DELETEs, UPDATEs, etc. Operations are automatically ordered by the Session’s unit of work dependency solver.

Database operations will be issued in the current transactional context and do not affect the state of the transaction, unless an error occurs, in which case the entire transaction is rolled back. You may flush() as often as you like within a transaction to move changes from Python to the database’s transaction buffer.

For autocommit Sessions with no active manual transaction, flush() will create a transaction on the fly that surrounds the entire set of operations into the flush.

Parameters:
objects – 
Optional; restricts the flush operation to operate only on elements that are in the given collection.
This feature is for an extremely narrow set of use cases where particular objects may need to be operated upon before the full flush() occurs. It is not intended for general use.

refresh(instanceattribute_names=Nonelockmode=None)

Expire and refresh the attributes on the given instance.

A query will be issued to the database and all attributes will be refreshed with their current database value.

Lazy-loaded relational attributes will remain lazily loaded, so that the instance-wide refresh operation will be followed immediately by the lazy load of that attribute.

Eagerly-loaded relational attributes will eagerly load within the single refresh operation.

Note that a highly isolated transaction will return the same values as were previously read in that same transaction, regardless of changes in database state outside of that transaction – usage ofrefresh() usually only makes sense if non-ORM SQL statement were emitted in the ongoing transaction, or if autocommit mode is turned on.

Parameters:
  • attribute_names – optional. An iterable collection of string attribute names indicating a subset of attributes to be refreshed.
  • lockmode – Passed to the Query as used by with_lockmode().

See also

Refreshing / Expiring – introductory material

Session.expire()

Session.expire_all()

-》好像如果是refresh,需要autocommit是打开了才可以?

结果refresh出错:

before refresh newEvent=<Event id=None user_openid=oswjmv4X0cCXcfkIwjoDfCkeTVVY title=u’\u6d4b\u8bd5session’>

<div–<——————————————————————————

[2016-09-04 21:30:48 +0000] [26600] [ERROR] Error handling request /creat_event
Traceback (most recent call last):
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/gunicorn/workers/sync.py”, line 135, in handle
    self.handle_request(listener, req, client, addr)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/gunicorn/workers/sync.py”, line 176, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1567, in handle_exception
    reraise(exc_type, exc_value, tb)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1641, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1544, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1639, in full_dispatch_request
    rv = self.dispatch_request()
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/flask/app.py”, line 1625, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File “/root/html/SIPEvents/sipevents/views.py”, line 743, in decorated_function
    return f(*args, **kwargs)
  File “/root/html/SIPEvents/sipevents/views.py”, line 916, in creat_event
    db.session.refresh(newEvent)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py”, line 157, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/sqlalchemy/orm/session.py”, line 1355, in refresh
    self._expire_state(state, attribute_names)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/sqlalchemy/orm/session.py”, line 1441, in _expire_state
    self._validate_persistent(state)
  File “/root/Envs/SIPEvents/lib/python2.7/site-packages/sqlalchemy/orm/session.py”, line 1869, in _validate_persistent
    state_str(state))
InvalidRequestError: Instance ‘<Event at 0x7fe3ba0a9490>’ is not persistent within this Session

换成:

        gLog.debug(“before flush newEvent=%s”, newEvent)
        # db.session.refresh(newEvent)
        db.session.flush()
        gLog.debug(“after  flush newEvent=%s”, newEvent)

结果:

是可以的:

before flush newEvent=<Event id=None user_openid=oswjmv4X0cCXcfkIwjoDfCkeTVVY title=u’test’>

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in views [/root/html/SIPEvents/sipevents/views.py:918]:
after  flush newEvent=<Event id=23 user_openid=oswjmv4X0cCXcfkIwjoDfCkeTVVY title=u’test’>

<div–<——————————————————————————

<div–<——————————————————————————

DEBUG in views [/root/html/SIPEvents/sipevents/views.py:920]:
added new event=<Event id=23 user_openid=oswjmv4X0cCXcfkIwjoDfCkeTVVY title=u’test’>

[总结]

SQLAlchemy中,在session去commit提交插入新数据之前,

可以通过:

db.session.flush()

即可使得,之前query出来的变量对象,已经获得了,相当于插入后的值

比如自增auto increment的id,就从None变成插入后的23了。

转载请注明:在路上 » [已解决]SQLAlchemy中如何得到db.session.commit后的新增的对象

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
84 queries in 0.195 seconds, using 22.17MB memory