were tutorial quick query one not multiple guide found for español create python sqlalchemy

python - tutorial - método de iteración sobre las columnas definidas del modelo sqlalchemy?



sqlalchemy relationship not null (6)

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 una gran cantidad de elementos específicos de SA.

¿Alguien sabe de una forma de obtener los id, y desc nombres 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 preferiría algo que se genere automáticamente para objetos más grandes.

Gracias por la asistencia.


Me doy cuenta de que esta es una vieja pregunta, pero acabo de encontrar el mismo requisito y me gustaría ofrecer una solución alternativa para los lectores futuros.

Como señala Josh, las JobStatus.__table__.columns nombres completos de los campos SQL, 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 atributo _data en el objeto de columna, que contiene los datos completos. Si miramos JobStatus.__table__.columns._data , se ve así:

{''desc'': Column(''desc'', Unicode(length=20), table=<jobstatus>), ''id'': Column(''id'', Integer(), table=<jobstatus>, primary_key=True, nullable=False)}

Desde aquí, simplemente puede llamar a JobStatus.__table__.columns._data.keys() que le proporciona una lista limpia y agradable:

[''id'', ''desc'']


Para obtener un método as_dict en todas mis clases, utilicé una clase Mixin que usa las técnicas descritas por .

class BaseMixin(object): def as_dict(self): result = {} for prop in class_mapper(self.__class__).iterate_properties: if isinstance(prop, ColumnProperty): result[prop.key] = getattr(self, prop.key) return result

Y luego úsala así en tus clases

class MyClass(BaseMixin, Base): pass

De esta forma, puede invocar lo siguiente en una instancia de MyClass .

> myclass = MyClass() > myclass.as_dict()

Espero que esto ayude.

He jugado con esto un poco más allá, de hecho necesitaba representar mis instancias como dict como la forma de un objeto HAL con sus enlaces a objetos relacionados. Así que he agregado esta pequeña magia aquí, que se rastreará sobre todas las propiedades de la clase, como la anterior, con la diferencia de que voy a rastrear más profundamente en Relaionship propiedades de Relaionship y generar links para estos automáticamente.

Tenga en cuenta que esto solo funcionará para las relaciones tienen una sola clave principal

from sqlalchemy.orm import class_mapper, ColumnProperty from functools import reduce def deepgetattr(obj, attr): """Recurses through an attribute chain to get the ultimate value.""" return reduce(getattr, attr.split(''.''), obj) class BaseMixin(object): def as_dict(self): IgnoreInstrumented = ( InstrumentedList, InstrumentedDict, InstrumentedSet ) result = {} for prop in class_mapper(self.__class__).iterate_properties: if isinstance(getattr(self, prop.key), IgnoreInstrumented): # All reverse relations are assigned to each related instances # we don''t need to link these, so we skip continue if isinstance(prop, ColumnProperty): # Add simple property to the dictionary with its value result[prop.key] = getattr(self, prop.key) if isinstance(prop, RelationshipProperty): # Construct links relaions if ''links'' not in result: result[''links''] = {} # Get value using nested class keys value = ( deepgetattr( self, prop.key + "." + prop.mapper.primary_key[0].key ) ) result[''links''][prop.key] = {} result[''links''][prop.key][''href''] = ( "/{}/{}".format(prop.key, value) ) return result


Puede obtener la lista de propiedades definidas del asignador. Para su caso, solo le interesan los objetos ColumnProperty.

from sqlalchemy.orm import class_mapper import sqlalchemy def attribute_names(cls): return [prop.key for prop in class_mapper(cls).iterate_properties if isinstance(prop, sqlalchemy.orm.ColumnProperty)]


Puede usar la siguiente función:

def __unicode__(self): return "[%s(%s)]" % (self.__class__.__name__, '', ''.join(''%s=%s'' % (k, self.__dict__[k]) for k in sorted(self.__dict__) if ''_sa_'' != k[:4]))

Excluirá los atributos mágicos de SA, pero no excluirá las relaciones. Así que, básicamente, podría cargar las dependencias, los padres, los niños, etc., lo que definitivamente no es deseable.

Pero en realidad es mucho más fácil porque si __table__ de Base , tienes un atributo __table__ , de modo que puedes hacer:

for c in JobStatus.__table__.columns: print c for c in JobStatus.__table__.foreign_keys: print c

Consulte Cómo descubrir las propiedades de tabla del objeto mapeado SQLAlchemy - pregunta similar.

Editar por Mike: vea funciones como Mapper.c y Mapper.mapped_table . Si usa 0.8 y más, también vea Mapper.attrs y funciones relacionadas.

Ejemplo para Mapper.attrs :

from sqlalchemy import inspect mapper = inspect(JobStatus) for column in mapper.attrs: print column.key


Sé que esta es una vieja pregunta, pero ¿qué hay de:

class JobStatus(Base): ... def columns(self): return [col for col in dir(self) if isinstance(col, db.Column)]

Luego, para obtener los nombres de las columnas: jobStatus.columns()

Eso devolvería [''id'', ''desc'']

Luego puede recorrer y hacer cosas con las columnas y valores:

for col in jobStatus.colums(): doStuff(getattr(jobStatus, col))


self.__table__.columns "solo" te dará las columnas definidas en esa clase particular, es decir, sin heredar. si necesita todo, use self.__mapper__.columns . en su ejemplo, probablemente use algo como esto:

class JobStatus(Base): ... def __iter__(self): values = vars(self) for attr in self.__mapper__.columns.keys(): if attr in values: yield attr, values[attr] def logme(self): return dict(self)