Quiero seleccionar (y devolver) un campo solo de mi base de datos con una "cláusula where". El codigo es:

from sqlalchemy.orm import load_only
    @application.route("/user", methods=['GET', 'POST'])
    def user():
        user_id = session.query(User, User.validation==request.cookies.get("validation")).options(load_only("id"))
        session.commit()
        return user_id

Esto falla y el rastreo es:

File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1478, in full_dispatch_request
response = self.make_response(rv)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1577, in make_response
rv = self.response_class.force_type(rv, request.environ)
File "/Library/Python/2.7/site-packages/werkzeug/wrappers.py", line 841, in force_type
response = BaseResponse(*_run_wsgi_app(response, environ))
File "/Library/Python/2.7/site-packages/werkzeug/wrappers.py", line 57, in _run_wsgi_app
return _run_wsgi_app(*args)
File "/Library/Python/2.7/site-packages/werkzeug/test.py", line 867, in run_wsgi_app
app_rv = app(environ, start_response)
TypeError: 'Query' object is not callable

¿Cómo puedo seleccionar y devolver solo la columna "id"? He intentado varias otras formas también pero también con fracaso. ¿Es "load_only" la opción correcta?

30
user1903663 10 may. 2016 a las 12:01

4 respuestas

La mejor respuesta

Un objeto Query acepta entidades para consultar como argumentos posicionales, así que simplemente pásalo User.id:

user_id = session.query(User.id).\
        filter(User.validation == request.cookies.get("validation")).\
        scalar()

scalar() devuelve el primer elemento del primer resultado o Ninguno, si no se encontraron filas. Provoca la excepción MultipleResultsFound para varias filas.

load_only() indica que solo el los atributos basados en columnas de una entidad deben cargarse y todos los demás, esperen la identidad, serán diferidos. Si necesita el objeto modelo User completo más adelante, este puede ser el camino a seguir. En ese caso, su consulta original debe cambiar a:

user = session.query(User).\
        filter(User.validation == request.cookies.get("validation")).\
        options(load_only("id")).\
        one()

one() devuelve exactamente un resultado o genera una excepción (0 o más de 1 resultado). Si acepta None como un valor de retorno válido para "ningún usuario encontrado", use one_or_none().

Tenga en cuenta que los predicados, los criterios de la cláusula WHERE, no deben pasarse al objeto Query como entidades, sino agregarse con filter().

Para colmo, las vistas en Flask esperan que devuelva uno de:

  • un objeto de respuesta válido
  • una cuerda
  • una tupla (response, status, headers)
  • una aplicación WSGI

La maquinaria tratará cualquier cosa que no sea un objeto de respuesta, una cadena o una tupla como una aplicación WSGI. En su código original, devolvió un objeto Query debido a la falta de llamada a scalar() o similar y luego se trató como una aplicación WSGI.

43
Ilja Everilä 12 ene. 2019 a las 07:46

El problema no tiene nada que ver con las consultas y la conexión db. Dentro de la declaración @ application.route ("/ user", method = ['GET', 'POST']) devuelve un user_id que es el resultado de una selección de la base de datos. En Flask debe devolver algo apropiado.

2
Alexey Smirnov 10 may. 2016 a las 09:52

Consultar el contenido de una columna en lugar de la tabla completa frasco-sqlalchemy, lo que supongo que puede darle una pista sobre sqlalchemy en sí mismo funcionaría, le lleva a consultar la sesión como lo está haciendo, con una sintaxis diferente.

Si su mesa se ve algo así como:

class User(...):
    id = db.Column(db.Integer, primary_key=True)
    ...

Puedes consultarlo con:

user_ids = session.query(User.id)
all_ids = user_ids.all()

Esto devuelve una lista de todos los ID de usuario.

3
ciacicode 10 may. 2016 a las 09:24

Tendría que hacer algo en este sentido:

session.query(Table.col1).filter(User.name=='Name')
4
Tkingovr 10 may. 2016 a las 09:21