2011-05-18 38 views
8

Usando SQLAlchemy, estoy tratando de imprimir todos los atributos de cada modelo que tengo de una manera similar a:Cómo imprimir todas las columnas en SQLAlchemy ORM

SELECT * from table; 

Sin embargo, me gustaría hacer algo con la información de la instancia de cada modelo a medida que lo obtengo. Hasta ahora el mejor que he sido capaz de llegar a es:

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

Y esto me dará lo que estoy buscando, pero es una manera bastante rotonda de conseguirlo. Yo tenía la esperanza de un atributo a lo largo de las líneas de:

m.attributes 
# or 
m.columns.values 

Siento que estoy perdiendo algo y no hay una mejor manera de hacer esto. Estoy haciendo esto porque imprimiré todo en archivos .CSV, y no quiero tener que especificar las columnas/atributos que me interesan, lo quiero todo (hay muchas columnas en mucho de modelos a ser impresos).

Respuesta

4

Eche un vistazo a la característica metadata reflection de SQLAchemy.

+0

El inspector parece ser lo que necesito, aplausos. – mrmagooey

+1

Usando el ORM sqlalchemy de matraz, pude obtener los nombres de las columnas a través de lo siguiente: tablas_de_datos .__ tabla __. Columnas – simoes

1

Puede que le interese lo que se me ocurrió para hacer esto.

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) 
5

Creo que esta es la manera más fácil:

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

__dict__ no siempre pueden ayudar. Yo uso keys = self._sa_instance_state.attrs.items() – n0nSmoker

0

utilizo esto porque es un poco más corto:

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

Sobre la base de Rodney L's respuesta:

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

Esta es una publicación anterior, pero me encontré con una p roblem con los nombres reales de las columnas de la base de datos que no coinciden con los nombres de los atributos asignados en la instancia. Terminamos yendo con esto:

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

Espero que ayude a alguien con el mismo problema!

+0

Muy útil. ¡Gracias! – clime

2

poner esto juntos y encontrado útil:

from sqlalchemy import create_engine 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 
engine = create_engine('mysql+pymysql://testuser:[email protected]: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() 

Y luego:

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

Ejemplo de salida 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']} 

O y luego:

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() 
4

Probablemente la solución más corta (ver la reciente documentation):

from sqlalchemy.inspection import inspect 
table = inspect(model) 
for column in table.c 
    print column.name 
2

estoy usando SQL Alchemy v 1.0.14 en Python 3.5.2

Suponiendo que se pueden conectar a un motor con create_engine(), Pude mostrar todas las columnas usando el siguiente código. Reemplace "mi cadena de conexión" y "mi nombre de tabla" con los valores apropiados.

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 

la última fila solo muestra los nombres de las columnas de la declaración anterior.

1
print repr(model.__table__) 

o sólo las columnas:

objeto
print str(list(model.__table__.columns)) 
Cuestiones relacionadas