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 id
y desc
de 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__.columns
le 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_mapper
debe importarse desqlalchemy.orm
inspect()
, 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
_data
atributo 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_dict
método en todas mis clases, utilicé unaMixin
clase 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
dict
como 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 lasRelaionship
propiedades y generarélinks
para 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, ColumnProperty
en 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