【问题标题】:When the sqlalchemy ORM class attributes are different from database columns, how to get a list of the ORM class attributes?当 sqlalchemy ORM 类属性与数据库列不同时,如何获取 ORM 类属性的列表?
【发布时间】:2015-03-12 21:26:47
【问题描述】:

假设您想在 sqlalchemy 中迭代 ORM 类的 ORM 属性。 因此,您需要一个 ORM 属性列表。您如何获得这份清单?

如果 ORM 类没有重命名属性,因此 ORM 属性与数据库列匹配,那么您可以使用以下解决方案: https://stackoverflow.com/a/24748320/1023033 (顺便说一句,在源代码文件 /lib/sqlalchemy/orm/base.py 中还有一个内置(私有)函数 _orm_columns() 似乎提供了这个功能)

但如果 python ORM 类的名称与数据库列的名称不同(例如在这 3 个 ORM 属性中):

>>> class User(Base):
...     __tablename__ = 'users'
...
...     id = Column('pkey', Integer, primary_key=True)
...     name = Column('user_name', String)
...     fullname = Column('human_name', String)

那么该方法不起作用。 那么,如何获取 Python 版本的 ORM 属性呢?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    这已经使用inspection system实现:

    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import inspect
    
    Base = declarative_base()
    
    class A(Base):
        __tablename__ = 'a'
        id = Column(Integer, primary_key=True)
        x = Column(Integer)
        y = Column(Integer)
    
    print inspect(A).c
    print inspect(A).c.x
    print inspect(A).column_attrs
    print inspect(A).column_attrs.x
    print inspect(A).column_attrs.x.expression
    

    http://docs.sqlalchemy.org/en/latest/core/inspection.html

    http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.all_orm_descriptors

    http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.columns

    http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.column_attrs

    http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.c

    【讨论】:

    • 属性列表可使用 .items() 方法获得,因此我不必事先知道属性的名称: print( inspect(python_orm_class).column_attrs.items() )
    • 关于如何通过检查获取信息的一个很好的概述:docs.sqlalchemy.org/en/rel_0_9/orm/…
    • 当我尝试这个时,我得到错误:没有检查系统可用于 ResultProxy 类型的对象
    • 我们什么时候才能看到将 ORM 对象转换为 dict 的简单内置方法(支持非循环递归关系等)?使用 Flask-SQLAlchemy 时,这样做会很棒:return jsonify([row.to_dict() for row in sqlalch_query.all()])
    【解决方案2】:

    我定义了一个 mixin 类来扩充

    Base = declarative_base()
    

    mixin 类定义为:

    import inspect
    import sqlalchemy as sqla 
    
    class orm_mixin_class(object):
        """Additional functionality wanted in orm classes (that inherit from Base)."""
    
        @classmethod
        def orm_class_info(cls):
            """
            Get info about the orm class (as opposed to the database table it is mapped to).
    
            Returns:
                list of dict where each dict describes a orm class attribute.  
                Keys: s_class_attribute_name
            """
            o_leaf_level_class = cls   # this turns out the be the leaf class instead of this mixin class
            l_orm_attribute_pairs = inspect.getmembers(o_leaf_level_class)
    
            l_orm_class_info_dicts = []
            for (s_class_attribute_name, o_attr_type) in l_orm_attribute_pairs:
                d_attr_info = {}
                b_orm_attribute = False
                try:
                    o_inspect = sqla.inspection.inspect(o_attr_type) 
    
                    if isinstance(o_inspect, sqla.orm.attributes.QueryableAttribute):
                        b_orm_attribute = True
                        d_attr_info['s_class_attribute_name'] = s_class_attribute_name
                except:
                    pass            
    
                if b_orm_attribute:
                    # only orm attributes have an entry in the output list
                    l_orm_class_info_dicts.append(d_attr_info)
    
            return(l_orm_class_info_dicts)
    

    所以ORM属性列表可以很容易地从方法调用中获得。

    ORM 类声明现在是:

    class User(Base, orm_mixin_class):
    

    【讨论】:

      猜你喜欢
      • 2015-03-02
      • 2021-03-26
      • 2010-12-30
      • 2010-10-18
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2012-02-17
      相关资源
      最近更新 更多