Tenho tentado descobrir como iterar a lista de colunas definidas em um modelo SQLAlchemy. Eu quero escrever alguns métodos de serialização e cópia para alguns modelos. Não posso simplesmente iterar sobre o, obj.__dict__
pois ele contém muitos itens específicos de SA.
Alguém sabe uma maneira de obter os nomes id
e a desc
partir do seguinte?
class JobStatus(Base):
__tablename__ = 'jobstatus'
id = Column(Integer, primary_key=True)
desc = Column(Unicode(20))
Neste pequeno caso, eu poderia facilmente criar um:
def logme(self):
return {'id': self.id, 'desc': self.desc}
mas eu prefiro algo que gere automaticamente o dict
(para objetos maiores).
fonte
__table__.columns
fornecerá os nomes dos campos SQL, não os nomes dos atributos que você usou nas suas definições ORM (se os dois forem diferentes).'_sa_' != k[:4]
paranot k.startswith('_sa_')
?inspect(JobStatus).columns.keys()
Você pode obter a lista de propriedades definidas do mapeador. Para o seu caso, você está interessado apenas em objetos ColumnProperty.
fonte
class_mapper
precisa ser importado desqlalchemy.orm
inspect()
, que retorna exatamente o mesmo objeto mapeador queclass_mapper()
. docs.sqlalchemy.org/en/latest/core/inspection.htmlSei que essa é uma questão antiga, mas acabo de me deparar com a mesma exigência e gostaria de oferecer uma solução alternativa para futuros leitores.
Como Josh observa, nomes completos de campos SQL serão retornados por
JobStatus.__table__.columns
, portanto, em vez do id do nome do campo original , você obterá jobstatus.id . Não é tão útil quanto poderia ser.A solução para obter uma lista de nomes de campo conforme foram originalmente definidos é examinar o
_data
atributo no objeto de coluna, que contém os dados completos. Se olharmosJobStatus.__table__.columns._data
, é assim:A partir daqui, você pode simplesmente ligar, o
JobStatus.__table__.columns._data.keys()
que lhe dá uma lista bonita e limpa:fonte
self.__table__.columns
irá "apenas" dar-lhe as colunas definidas naquela classe particular, ou seja, sem as herdadas. se precisar de tudo, useself.__mapper__.columns
. no seu exemplo eu provavelmente usaria algo assim:fonte
Supondo que você esteja usando o mapeamento declarativo do SQLAlchemy, você pode usar o
__mapper__
atributo para chegar ao mapeador de classe. Para obter todos os atributos mapeados (incluindo relacionamentos):Se quiser nomes de coluna estritamente, use
obj.__mapper__.column_attrs.keys()
. Consulte a documentação para outras visualizações.https://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.attrs
fonte
Para obter um
as_dict
método em todas as minhas aulas, usei umaMixin
classe que usa as técnicas descritas por Ants Aasma .E então use-o assim em suas aulas
Dessa forma, você pode invocar o seguinte em uma instância de
MyClass
.Espero que isto ajude.
Eu brinquei com isso um pouco mais adiante, na verdade eu precisava renderizar minhas instâncias
dict
como a forma de um objeto HAL com seus links para objetos relacionados. Então, adicionei essa pequena mágica aqui, que irá rastrear todas as propriedades da classe igual à anterior, com a diferença de que eu irei rastrear mais profundamente nasRelaionship
propriedades e gerarlinks
para elas automaticamente.Observe que isso só funcionará para relacionamentos com uma única chave primária
fonte
from sqlalchemy.orm import class_mapper, ColumnProperty
acima de seu snippet de códigoretorna um dict em que as chaves são nomes de atributos e valores os valores do objeto.
/! \ há um atributo suplementar: '_sa_instance_state' mas você pode lidar com isso :)
fonte
Eu sei que esta é uma pergunta antiga, mas e quanto a:
Então, para obter os nomes das colunas:
jobStatus.columns()
Isso iria voltar
['id', 'desc']
Em seguida, você pode fazer um loop e fazer coisas com as colunas e valores:
fonte