web-dev-qa-db-fra.com

Requête pour une liste d'attributs au lieu de tuples dans SQLAlchemy

J'interroge les identifiants d'un modèle et récupère une liste de tuples (int,) plutôt qu'une liste d'identifiants. Existe-t-il un moyen d'interroger directement l'attribut?

result = session.query(MyModel.id).all()

Je réalise qu'il est possible de faire 

results = [r for (r,) in results]

Est-il possible pour la requête de renvoyer ce formulaire directement au lieu de le traiter moi-même?

9
PapeK24

Lors du passage dans des descripteurs instrumentés par ORM, tels qu'une colonne, chaque résultat est un nommé Tuple , même pour une seule colonne. Vous pouvez utiliser le nom de colonne dans une compréhension de liste pour "aplatir" la liste (vous pouvez supprimer l'appel .all(), l'itération récupère également les objets):

result = [r.id for r in session.query(MyModel.id)]

ou utilisez le fait qu'il s'agisse d'un tuple lorsque vous bouclez une boucle for et décompressez-le dans un tuple à un seul élément de cibles:

result = session.query(MyModel.id)
for id, in result:
    # do something with the id

Ce dernier pourrait également être utilisé dans une liste de compréhension:

[id for id, in session.query(MyModel.id)]

Vous n'avez pas vraiment d'options pour forcer les résultats de la ligne à être seulement la valeur unique id.

14
Martijn Pieters

Il est étrange que SQLalchemy ne fournisse pas une solution appropriée. Dans sqlalchemy, si vous sélectionnez une variable membre telle qu'une colonne, chaque résultat correspond à un tuple nommé, comme l'a dit @Martijn. Je suis venu à une solution pour cela en utilisant la fonction Zip de python

Documentation officielle Zip

Zip (seq1 [ seq2 [...]]) -> [(seq1 [0], seq2 [0] ...), (...)] Retourne une liste de tuples, où chaque Tuple contient le i-ème élément de chacune des séquences d'arguments. La liste renvoyée est tronquée de longueur à la longueur de la séquence d'arguments la plus courte.

Venir à votre exemple

result = session.query(MyModel.id).all()
result = Zip(*result)[0]

Sortie:

[id1, id2, id3...]

Comment cela fonctionnera-t-il, la liste des n-uplets donnés en argument sera aplatie si vous passez la liste comme 

[(key11, key21), (key12,key22)]

Zip convertira cette liste de tuples en 

[(key11, key12), (key21, key22)]

Dans votre cas, vous voulez que chaque valeur initiale de tupe qui est du MyModel afin que vous puissiez prendre le 0e tuple de la liste.

1
anand tripathi