美文网首页
sqlalchemy的大坑

sqlalchemy的大坑

作者: 晓函 | 来源:发表于2020-04-19 22:52 被阅读0次

从flask-sqlalchemy转到sqlalchemy,
少了一个特性,那就是每次请求后都自动commit(),现在需要再每次session.add后都自己session.commit()

这次遇到一个坑,想通过user.dict把user转为json,然而打印居然有时为空

        user = db.session.query(User).filter_by(mobile=mobile).first()
        if user and user.verify_password(password=password):
            login = db.get_or_insert(Login, user_id=user.id)
            login.ip = request.headers.get('X-Forwarded-For') or request.remote_addr
            db.session.add(login)
            print(user.__dict__)
            db.session.commit()
            print(user.__dict__)
            a=user.id
            print(user.__dict__)

第一次print输出

{ 'avatar': None,'role': 4, 'intro': None, 'boss_id': 1, 'mobile': '13000000001', 'id': 1, 'nick': '王一', 'words': None, '_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7fe382f470b8>}

db.session.commit()后的print就输出

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7fe382f470b8>}

其他的数据都不见了,被commit清空了?
最后跟着
a=user.id后print输出,

{ 'avatar': None,'role': 4, 'intro': None, 'boss_id': 1, 'mobile': '13000000001', 'id': 1, 'nick': '王一', 'words': None, '_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7fe382f470b8>}

数据又出来了,判断:
_sa_instance_state有值,映射关系应该还是在都,只是dict被清空了,当调用Model的成员的时候,则自动把实例映射读取回来,这样就可以通过user.dict看到了user成员了。
打印出

_sa_instance_state:{'identity_token': None, '_strong_obj': None, '_instance_dict': <weakref at 0x1093265e8; to 'WeakInstanceDict' at 0x109328748>, 'class_': <class 'app.models.User'>, 'session_id': 1, 'runid': 1, 'committed_state': {}, 'expired_attributes': { 'words', 'code', 'boss_id', 'mobile', 'time', 'senior_id', 'leader_id', 'status', 'intro', 'nick', 'role', 'id', 'avatar'}, 'manager': <ClassManager of <class 'app.models.User'> at 108ef0f98>, 'obj': <weakref at 0x109382638; to 'User' at 0x10938fac8>, 'key': (<class 'app.models.User'>, (1,), None), 'load_path': CachingEntityRegistry((<Mapper at 0x108f01780; User>,)), 'load_options': set(), 'expired': True}

发现里面写着expired_attributes,和'expired': True,可见commit()后,之前的user对象就作为过期的处理,成员全部清空。

如何稳定遍历Model呢?
解决方法:

def to_dict(obj):
            dic = {}
            dic_columns = obj.__table__.columns
            # 保证都是字符串和数字
            types = [str,int,float,bool]
            #注意,obj.__dict__会在commit后被作为过期对象清空dict,所以保险的办法还是用columns
            for k,tmp in dic_columns.items():
                # k=nick,tmp=user.nick
                v = getattr(obj,k,None)
                dic[k] = str(v) if v and type(v) not in types else v
            return dic

print(to_dict(user))

相关文章

网友评论

      本文标题:sqlalchemy的大坑

      本文链接:https://www.haomeiwen.com/subject/sqlwbhtx.html