Consulta Flask SQLAlchemy, especifique nomes de colunas

125

Como especifico a coluna que desejo na minha consulta usando um modelo (ele seleciona todas as colunas por padrão)? Eu sei como fazer isso com a sessão sqlalchmey:, session.query(self.col1)mas como faço com modelos? Eu não posso fazer SomeModel.query(). Há algum jeito?

Matthew Scragg
fonte

Respostas:

220

Você pode usar o with_entities()método para restringir quais colunas você gostaria de retornar no resultado. ( documentação )

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

Dependendo dos seus requisitos, você também pode achar que os diferidos são úteis. Eles permitem retornar o objeto completo, mas restringem as colunas que passam pelo fio.

David McKeone
fonte
21
with_entities () faz com que all () produza tuplas de valores de coluna, não objetos!
kolypto
10
kolypto: Produz o que você pede. SomeModel.query.with_entities (SomeModel) produziria o objeto. Assim como session.query (SomeModel.col1, SomeModel.col2) produziria tuplas de valores de coluna. Adiados são o que você usaria se não quiser que as colunas cheguem ao fio, mas deseje o objeto inteiro de qualquer maneira.
David McKeone 06/02
2
Obrigado, funciona. Mas como podemos atribuir um alias ao campo? Porque no meu caso, estou usando JOIN e conflito IDcampo que está presente em ambos mesa
Mitul Shah
Sim, eu tenho a mesma pergunta com @MitulShah, como definir alias?
Nam G VU
Para o alias, veja esta breve resposta abaixo, ie. use .label() stackoverflow.com/a/11535992/248616
Nam G VU
69
session.query().with_entities(SomeModel.col1)

é o mesmo que

session.query(SomeModel.col1)

para alias, podemos usar .label ()

session.query(SomeModel.col1.label('some alias name'))
Salil
fonte
2
O segundo parece mais lógico e é mais curto - win / win
fgblomqvist
7
Sua primeira afirmação está errada. Você precisa de parênteses. Assim, deve ler-se:session.query().with_entities(SomeModel.col1)
JGFMK
As primeiras (e terceiras) opções são as melhores, de longe, se você deseja reutilizar objetos de consulta existentes, especialmente no caso de executar várias subconsultas complexas.
21319 Jamie Strauss
36

Você pode usar a função load_only :

from sqlalchemy.orm import load_only

fields = ['name', 'addr', 'phone', 'url']
companies = session.query(SomeModel).options(load_only(*fields)).all()
Vlad Bezden
fonte
1
Esta solução é a melhor, pois ainda está funcionando como um Objeto, não apenas na lista de resultados.
rborodinov 02/07/19
Parabéns a você por esta solução. Tem muitas vantagens: - retorna exatamente o mesmo tipo de objeto que .first()e .one()(que carregará campos e relações preguiçosos / ansiosos), - pode ser definido como componente de consulta
Damien
o código está limpo, mas a consulta sql seleciona todos os campos do banco de dados. Eu usei with_entitiescomo indicado na resposta aceita e a consulta selecionou apenas esses campos /.
Srikanth Jeeva
11

Você pode usar Model.query, porque a Model(ou geralmente sua classe base, especialmente nos casos em que a extensão declarativa é usada) é atribuída Sesssion.query_property. Nesse caso, Model.queryé equivalente a Session.query(Model).

Não estou ciente da maneira de modificar as colunas retornadas pela consulta (exceto adicionando mais usando add_columns()).
Portanto, sua melhor chance é usar o Session.query(Model.col1, Model.col2, ...)(como já mostrado por Salil).

furgão
fonte
Acredito que também pode haver uma maneira de fazer isso com uma lista de colunas para valores de consulta (), docs.sqlalchemy.org/en/latest/orm/… - mas o açúcar sintático da lista me escapa no momento.
JGFMK
3

Você pode usar Query.values, Query.values

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

gaozhidf
fonte
-11

Um exemplo aqui:

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

Consulto o banco de dados para filmes com classificação <> 0 e, em seguida, ordeno-os classificando com a classificação mais alta primeiro.

Dê uma olhada aqui: Selecionar, Inserir, Excluir no Flask-SQLAlchemy

happygoat
fonte