He estado tratando de averiguar cómo iterar sobre la lista de columnas definidas en un modelo SQLAlchemy. Lo quiero para escribir algunos métodos de serialización y copia en un par de modelos. No puedo simplemente iterar sobre el obj.__dict__ya que contiene muchos elementos específicos de SA.
¿Alguien conoce una forma de obtener los nombres idy descde los siguientes?
class JobStatus(Base):
__tablename__ = 'jobstatus'
id = Column(Integer, primary_key=True)
desc = Column(Unicode(20))
En este pequeño caso, podría crear fácilmente un:
def logme(self):
return {'id': self.id, 'desc': self.desc}
pero prefiero algo que genere automáticamente dict(para objetos más grandes).
fuente

__table__.columnsle dará los nombres de los campos SQL, no los nombres de los atributos que ha utilizado en sus definiciones ORM (si los dos difieren).'_sa_' != k[:4]anot k.startswith('_sa_')?inspect(JobStatus).columns.keys()Puede obtener la lista de propiedades definidas del asignador. En su caso, solo le interesan los objetos ColumnProperty.
fuente
class_mapperdebe importarse desqlalchemy.orminspect(), que devuelve exactamente el mismo objeto mapeador queclass_mapper(). docs.sqlalchemy.org/en/latest/core/inspection.htmlMe doy cuenta de que esta es una pregunta antigua, pero acabo de encontrar el mismo requisito y me gustaría ofrecer una solución alternativa a los futuros lectores.
Como señala Josh, los nombres de campo SQL completos serán devueltos por
JobStatus.__table__.columns, por lo que , en lugar del id del nombre del campo original , obtendrá jobstatus.id . No es tan útil como podría ser.La solución para obtener una lista de nombres de campo como se definieron originalmente es buscar el
_dataatributo en el objeto de columna, que contiene los datos completos. Si lo miramosJobStatus.__table__.columns._data, se ve así:Desde aquí, simplemente puede llamar, lo
JobStatus.__table__.columns._data.keys()que le brinda una lista agradable y limpia:fuente
self.__table__.columns"sólo" le dará las columnas definidas en esa clase en particular, es decir, sin las heredadas. si lo necesita todo, utiliceself.__mapper__.columns. en su ejemplo probablemente usaría algo como esto:fuente
Suponiendo que está usando el mapeo declarativo de SQLAlchemy, puede usar el
__mapper__atributo para llegar al mapeador de clases. Para obtener todos los atributos asignados (incluidas las relaciones):Si desea nombres de columna estrictamente, use
obj.__mapper__.column_attrs.keys(). Consulte la documentación para conocer otras vistas.https://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.attrs
fuente
Para obtener un
as_dictmétodo en todas mis clases, utilicé unaMixinclase que utiliza las técnicas descritas por Ants Aasma .Y luego úsalo así en tus clases.
De esa forma, puede invocar lo siguiente en una instancia de
MyClass.Espero que esto ayude.
He jugado un poco más con esto, en realidad necesitaba renderizar mis instancias
dictcomo la forma de un objeto HAL con sus enlaces a objetos relacionados. Así que agregué esta pequeña magia aquí abajo, que rastreará todas las propiedades de la clase igual que la anterior, con la diferencia de que rastrearé más profundamente en lasRelaionshippropiedades y generarélinkspara estas automáticamente.Tenga en cuenta que esto solo funcionará para las relaciones que tengan una única clave principal
fuente
from sqlalchemy.orm import class_mapper, ColumnPropertyen la parte superior del fragmento de códigodevuelve un dict donde las claves son nombres de atributos y valora los valores del objeto.
/! \ hay un atributo suplementario: '_sa_instance_state' pero puedes manejarlo :)
fuente
Sé que esta es una vieja pregunta, pero ¿qué pasa con:
Luego, para obtener los nombres de las columnas:
jobStatus.columns()Que volvería
['id', 'desc']Luego puede recorrer y hacer cosas con las columnas y valores:
fuente