美文网首页
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