Requête Flask SQLAlchemy, spécifiez les noms de colonne

126

Comment spécifier la colonne que je souhaite dans ma requête à l'aide d'un modèle (il sélectionne toutes les colonnes par défaut)? Je sais comment faire cela avec la session sqlalchmey:, session.query(self.col1)mais comment puis-je le faire avec des modèles? Je ne peux pas faire SomeModel.query(). Y a-t-il un moyen?

Matthew Scragg
la source

Réponses:

221

Vous pouvez utiliser la with_entities()méthode pour restreindre les colonnes que vous souhaitez renvoyer dans le résultat. ( documentation )

result = SomeModel.query.with_entities(SomeModel.col1, SomeModel.col2)

En fonction de vos besoins, vous trouverez peut-être également utile les reports. Ils vous permettent de renvoyer l'objet complet mais limitent les colonnes qui passent sur le fil.

David McKeone
la source
21
with_entities () fait que all () donne des tuples de valeurs de colonne, pas d'objets!
kolypto
10
kolypto: Il donne tout ce que vous lui demandez de céder. SomeModel.query.with_entities (SomeModel) donnerait l'objet. Tout comme session.query (SomeModel.col1, SomeModel.col2) produirait des tuples de valeurs de colonne. Les différés sont ce que vous utiliseriez si vous ne voulez pas que les colonnes passent sur le fil, mais que vous voulez quand même l'objet entier.
David McKeone
2
Merci ça marche. Mais comment pourrions-nous attribuer un alias au champ? Parce que dans mon cas, j'utilise JOIN et le IDchamp de conflit qui est présent dans les deux tableaux
Mitul Shah
Ouais, j'ai la même question avec @MitulShah, comment définir un alias?
Nam G VU
Pour l'alias, consultez cette brève réponse ci-dessous, c'est-à-dire. utilisez .label() stackoverflow.com/a/11535992/248616
Nam G VU
69
session.query().with_entities(SomeModel.col1)

est le même que

session.query(SomeModel.col1)

pour alias, nous pouvons utiliser .label ()

session.query(SomeModel.col1.label('some alias name'))
Salil
la source
2
Le second semble à la fois plus logique et plus court - gagnant / gagnant
fgblomqvist
7
Votre première déclaration est fausse. Vous avez besoin de parenthèses. Donc, il devrait lire:session.query().with_entities(SomeModel.col1)
JGFMK
Les première (et troisième) options sont de loin les meilleures si vous souhaitez réutiliser des objets de requête existants, en particulier dans le cas de l'exécution de plusieurs sous-requêtes complexes.
Jamie Strauss
36

Vous pouvez utiliser la fonction load_only :

from sqlalchemy.orm import load_only

fields = ['name', 'addr', 'phone', 'url']
companies = session.query(SomeModel).options(load_only(*fields)).all()
Vlad Bezden
la source
1
Cette solution est la meilleure car elle fonctionne toujours en tant qu'objet et non seulement en tant que liste de résultats.
rborodinov le
Bravo à vous pour cette solution. Il présente de nombreux avantages: - retourne exactement le même type d'objet que .first()et .one()(qui chargera les champs et les relations paresseux / impatients), - peut être défini comme composant de requête
Damien le
le code est propre mais la requête sql sélectionne tous les champs de la base de données. J'ai utilisé with_entitiescomme indiqué dans la réponse acceptée et la requête n'a sélectionné que les champs /.
Srikanth Jeeva
11

Vous pouvez utiliser Model.query, car le Model(ou généralement sa classe de base, en particulier dans les cas où l'extension déclarative est utilisée) est affecté Sesssion.query_property. Dans ce cas, le Model.queryéquivaut à Session.query(Model).

Je ne connais pas la manière de modifier les colonnes retournées par la requête (sauf en ajoutant plus à l'aide add_columns()).
Donc, votre meilleur coup est d'utiliser le Session.query(Model.col1, Model.col2, ...)(comme déjà montré par Salil).

van
la source
Je crois qu'il peut également y avoir un moyen de le faire avec une liste de colonnes pour les valeurs de requête () aussi, docs.sqlalchemy.org/en/latest/orm / ... - mais le sucre syntaxique pour la liste m'échappe pour le moment.
JGFMK
3

Vous pouvez utiliser Query.values, Query.values

session.query(SomeModel).values('id', 'user')

gaozhidf
la source
-11

Un exemple ici:

movies = Movie.query.filter(Movie.rating != 0).order_by(desc(Movie.rating)).all()

J'interroge la base de données pour les films avec une note <> 0, puis je les commande par note avec la note la plus élevée en premier.

Jetez un œil ici: Sélectionnez, Insérez, Supprimez dans Flask-SQLAlchemy

happygoat
la source