127 votes

méthode d'itération sur les colonnes définies du modèle sqlalchemy?

J'ai été à essayer de comprendre comment itérer sur la liste des colonnes définies dans un modèle SqlAlchemy. Je le veux pour l'écriture de certains de sérialisation et de méthodes de copie pour un couple de modèles. Je ne peux pas juste faire une itération sur l'obj.dict car il contient beaucoup de SA à des éléments spécifiques.

Quelqu'un connais un moyen de simplement obtenir l'id, et desc noms de la suivante?

class JobStatus(Base):
    __tablename__ = 'jobstatus'

    id = Column(Integer, primary_key=True)
    desc = Column(Unicode(20))

Dans cette petite affaire, j'ai pu facilement créer un:

def logme(self):
    return {'id': self.id, 'desc': self.desc}

mais je préfère quelque chose qui a été auto génération pour les objets plus grands.

Merci pour l'aide.

110voto

van Points 18052

Vous pouvez utiliser la fonction suivante:

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

Elle exclut de SA magie attributs, mais n'exclut pas les relations. Donc, fondamentalement, il pourrait charger les dépendances, les parents, les enfants, etc, qui n'est certainement pas souhaitable.

Mais il est effectivement beaucoup plus facile parce que si vous héritez de Base, vous avez un __table__ d'attribut, de sorte que vous pouvez faire:

for c in JobStatus.__table__.columns:
    print c

for c in JobStatus.__table__.foreign_keys:
    print c

Voir Comment découvrir les propriétés de la table de SQLAlchemy objet associé - question similaire.

Edit par Mike: consultez des fonctions telles que Mappeur.c et Mappeur.mapped_table. Si à l'aide de 0,8 et supérieur également voir Mappeur.attrs et les fonctions associées.

Exemple pour Mapper.attrs:

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

66voto

Ants Aasma Points 22921

Vous pouvez obtenir la liste des propriétés définies à partir du mappeur. Dans votre cas, seuls les objets ColumnProperty vous intéressent.

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

36voto

morphics Points 101

Je me rends compte que c'est une vieille question, mais je viens de trouver la même exigence et que vous voulez proposer une solution alternative pour les futurs lecteurs.

Comme Josh notes, SQL complète des noms de champ sera retourné par JobStatus.__table__.columns, alors plutôt que de l'original nom du champ id, vous obtiendrez jobstatus.id. Pas aussi utile qu'elle pourrait être.

La solution à l'obtention d'une liste de noms de champs qu'ils ont été initialement définies est de regarder l' _data l'attribut dans l'objet de colonne, qui contient l'ensemble des données. Si l'on regarde JobStatus.__table__.columns._data, il ressemble à ceci:

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

De là, vous pouvez simplement appeler JobStatus.__table__.columns._data.keys() qui vous donne une belle, propre liste:

['id', 'desc']

14voto

Andi Zeidler Points 71

self.__table__.columns ne vous "donnera" que les colonnes définies dans cette classe particulière, c'est-à-dire sans celles héritées. si vous avez besoin de tous, utilisez self.__mapper__.columns . dans votre exemple, j'utiliserais probablement quelque chose comme ceci:

 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)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X