SQLAlchemy: Obtención de un solo objeto para unir varias tablas

DB – configuración de SQLAlchemy

Considere una configuración clásica de dos tablas: user y api_key , representadas por objetos SQLAlchemy como:

 class User(Base): __tablename__ = 'user' user_id = Column(String) user_name = Column(String) vioozer_api_key = Column(String, ForeignKey("api_key.api_key")) class ApiKey(Base): __tablename__ = 'api_key' api_key = Column(String(37), primary_key=True) 

Otros campos omitidos por claridad.

Mi consulta

Supongamos que quiero obtener el nombre de usuario y la clave api para un ID de usuario específico:

 user, api_key = database.db_session.query(User, ApiKey)\ .join(ApiKey, User.vioozer_api_key==ApiKey.api_key)\ .filter(User.user_id=='user_00000000000000000000000000000000').first() 

Obtengo dos objetos: user y api_key , desde donde puedo obtener user.name y api_key.api_key .

El problema

Me gustaría envolver esta llamada con una función, que devolvería un solo objeto cuyos campos serían la unión de los campos de user y los campos api_key , de la misma manera que una join SQL devuelve una tabla con las columnas de ambas tablas unidas. ¿Existe alguna forma de obtener automáticamente un objeto cuyos campos sean la unión de los campos de ambas tablas?

Que he intentado

Puedo definir una clase de asignador para cada operación de unión, pero me pregunto si el mapeo podría hacerse automáticamente.

En lugar de consultar objetos, busque una lista de campos, en cuyo caso SQLAlchemy devuelve instancias de KeyedTuple , que ofrece el método KeyedTuple._asdict() que puede usar para devolver un diccionario arbitrario:

 def my_function(user_id): row = database.db_session.query(User.name, ApiKey.api_key)\ .join(ApiKey, User.vioozer_api_key==ApiKey.api_key)\ .filter(User.user_id==user_id).first() return row._asdict() my_data = my_function('user_00000000000000000000000000000000') 

Pero para su consulta en particular, no necesita siquiera unirse a ApiKey ya que el campo api_key está presente en la tabla de User :

 row = database.db_session.query(User.name, User.api_key)\ .filter(User.user_id==user_id).first() 

Yo agregaría una relación api_key en User :

 class User(Base): __tablename__ = 'user' user_id = Column(String) user_name = Column(String) vioozer_api_key = Column(String, ForeignKey("api_key.api_key")) api_key = Relationship('ApiKey', uselist=False) 

Entonces puedes hacer una consulta como esta:

 >>> user = database.db_session.query(User)\ .filter(User.user_id=='user_00000000000000000000000000000000').first() >>> user.api_key