【问题标题】:How to print all columns in SQLAlchemy ORM如何打印 SQLAlchemy ORM 中的所有列
【发布时间】:2011-05-18 02:45:24
【问题描述】:

使用 SQLAlchemy,我尝试以类似于以下方式打印出每个模型的所有属性:

SELECT * from table;

但是,我想在获得每个模型实例信息时对其进行处理。到目前为止,我能想到的最好的是:

for m in session.query(model).all():
    print [getattr(m, x.__str__().split('.')[1]) for x in model.__table__.columns]
    # additional code 

这会给我我正在寻找的东西,但这是一种相当迂回的获取方式。我有点希望有一个类似的属性:

m.attributes 
# or 
m.columns.values

我觉得我错过了一些东西,并且有更好的方法来做到这一点。我这样做是因为我会将所有内容打印到 .CSV 文件中,并且我不想指定我感兴趣的列/属性,我想要所有内容(很多列中有很多要打印的模型)。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    这是一篇旧帖子,但我遇到了实际数据库列名称与实例上映射的属性名称不匹配的问题。我们最终选择了这个:

    from sqlalchemy import inspect
    inst = inspect(model)
    attr_names = [c_attr.key for c_attr in inst.mapper.column_attrs]
    

    希望能帮助遇到同样问题的人!

    【讨论】:

    • 非常有用。谢谢!
    • 同样,如果您正在寻找关系:rel_names = [rel.key for rel in inst.mapper.relationships]。您还可以找到同义词和复合词:docs.sqlalchemy.org/en/13/orm/…
    【解决方案2】:

    可能是最短的解决方案(参见最近的documentation):

    from sqlalchemy.inspection import inspect
    columns = [column.name for column in inspect(model).c]
    

    如果将最后一行改写成三行,可能看起来更易读:

    table = inspect(model)
    for column in table.c:
        print column.name
    

    【讨论】:

    • 不错的解决方案,这解决了我的问题
    • 这也适用于 flask-sqlalchemy 设置
    【解决方案3】:

    以 Rodney L 的回答为基础:

    model = MYMODEL
    columns = [m.key for m in model.__table__.columns]
    

    【讨论】:

      【解决方案4】:

      看看 SQLAchemy 的 metadata reflection 功能。

      可以指示 Table 对象从数据库中已经存在的相应数据库模式对象中加载有关其自身的信息。这个过程称为反射。

      【讨论】:

      • 使用flask的sqlalchemy ORM,我能够通过以下方式获取列名:data_table.__table__.columns
      • {i.name: getattr(m, i.name) for i in m.__table__.columns} 这对我来说很好。
      • 链接似乎已损坏。您能否粘贴一些示例代码,“元数据反射”应该如何工作?此链接是否指向正确的检查,注意get_columns 功能? docs.sqlalchemy.org/en/13/core/…
      【解决方案5】:

      我相信这是最简单的方法:

      print [cname for cname in m.__dict__.keys()]
      

      编辑:我上面使用 sqlalchemy.inspection.inspect() 的答案似乎是一个更好的解决方案。

      【讨论】:

      • dict 并不总是有帮助。我使用 keys = self._sa_instance_state.attrs.items()
      • 没有帮助..如果我们在模型下定义了多个函数,这将得到这些函数
      【解决方案6】:
      print repr(model.__table__)
      

      或者只是列:

      print str(list(model.__table__.columns))
      

      【讨论】:

        【解决方案7】:

        把它放在一起,发现它很有帮助:

        from sqlalchemy import create_engine
        from sqlalchemy.ext.declarative import declarative_base
        from sqlalchemy.orm import sessionmaker
        engine = create_engine('mysql+pymysql://testuser:password@localhost:3306/testdb')
        DeclarativeBase = declarative_base()
        metadata = DeclarativeBase.metadata
        metadata.bind = engine
        
        
        # configure Session class with desired options
        Session = sessionmaker()
        
        # associate it with our custom Session class
        Session.configure(bind=engine)
        
        # work with the session
        session = Session()
        

        然后:

        d = {k: metadata.tables[k].columns.keys() for k in metadata.tables.keys()}
        

        示例输出print(d):

        {'orderdetails': ['orderNumber', 'productCode', 'quantityOrdered', 'priceEach', 'orderLineNumber'], 
        'offices': ['addressLine1', 'addressLine2', 'city', 'country', 'officeCode', 'phone', 'postalCode', 'state', 'territory'],
        'orders': ['comments', 'customerNumber', 'orderDate', 'orderNumber', 'requiredDate', 'shippedDate', 'status'],
        'products': ['MSRP', 'buyPrice', 'productCode', 'productDescription', 'productLine', 'productName', 'productScale', 'productVendor', 'quantityInStock'],
        'employees': ['employeeNumber', 'lastName', 'firstName', 'extension', 'email', 'officeCode', 'reportsTo', 'jobTitle'], 
        'customers': ['addressLine1', 'addressLine2', 'city', 'contactFirstName', 'contactLastName', 'country', 'creditLimit', 'customerName', 'customerNumber', 'phone', 'postalCode', 'salesRepEmployeeNumber', 'state'],
        'productlines': ['htmlDescription', 'image', 'productLine', 'textDescription'],
        'payments': ['amount', 'checkNumber', 'customerNumber', 'paymentDate']}
        

        或然后:

        from sqlalchemy.sql import text
        cmd = "SELECT * FROM information_schema.columns WHERE table_schema = :db ORDER BY table_name,ordinal_position"
        result = session.execute(
                    text(cmd),
                    {"db": "classicmodels"}
                )
        result.fetchall()
        

        【讨论】:

          【解决方案8】:

          我在 Python 3.5.2 上使用 SQL Alchemy v 1.0.14

          假设您可以使用 create_engine() 连接到引擎,我可以使用以下代码显示所有列。将“我的连接字符串”和“我的表名”替换为适当的值。

          from sqlalchemy import create_engine, MetaData, Table, select
          
          engine = create_engine('my connection string')
          
          conn = engine.connect()
          metadata = MetaData(conn)
          t = Table("my table name", metadata, autoload=True)
          columns = [m.key for m in t.columns]
          columns
          

          最后一行只显示上一条语句中的列名。

          【讨论】:

            【解决方案9】:

            你可能对我想出的办法感兴趣。

            from sqlalchemy.orm import class_mapper
            import collections
            
            # structure returned by get_metadata function.
            MetaDataTuple = collections.namedtuple("MetaDataTuple", 
                    "coltype, colname, default, m2m, nullable, uselist, collection")
            
            
            def get_metadata_iterator(class_):
                for prop in class_mapper(class_).iterate_properties:
                    name = prop.key
                    if name.startswith("_") or name == "id" or name.endswith("_id"):
                        continue
                    md = _get_column_metadata(prop)
                    if md is None:
                        continue
                    yield md
            
            
            def get_column_metadata(class_, colname):
                prop = class_mapper(class_).get_property(colname)
                md = _get_column_metadata(prop)
                if md is None:
                    raise ValueError("Not a column name: %r." % (colname,))
                return md
            
            
            def _get_column_metadata(prop):
                name = prop.key
                m2m = False
                default = None
                nullable = None
                uselist = False
                collection = None
                proptype = type(prop)
                if proptype is ColumnProperty:
                    coltype = type(prop.columns[0].type).__name__
                    try:
                        default = prop.columns[0].default
                    except AttributeError:
                        default = None
                    else:
                        if default is not None:
                            default = default.arg(None)
                    nullable = prop.columns[0].nullable
                elif proptype is RelationshipProperty:
                    coltype = RelationshipProperty.__name__
                    m2m = prop.secondary is not None
                    nullable = prop.local_side[0].nullable
                    uselist = prop.uselist
                    if prop.collection_class is not None:
                        collection = type(prop.collection_class()).__name__
                    else:
                        collection = "list"
                else:
                    return None
                return MetaDataTuple(coltype, str(name), default, m2m, nullable, uselist, collection)
            

            【讨论】:

              【解决方案10】:

              我使用它是因为它略短:

              for m in session.query(*model.__table__.columns).all():
                  print m
              

              【讨论】:

                猜你喜欢
                • 2022-10-02
                • 2020-03-30
                • 1970-01-01
                • 1970-01-01
                • 2018-03-02
                • 2021-01-14
                • 2016-09-25
                • 1970-01-01
                • 2011-02-13
                相关资源
                最近更新 更多