SQLAlchemy: Expresión híbrida con relación

Tengo dos modelos Flask-SQLAlchemy con una relación simple de uno a muchos, como el siguiente ejemplo:

class School(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30)) address = db.Column(db.String(30)) class Teacher(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30)) id_school = db.Column(db.Integer, db.ForeignKey(School.id)) school = relationship('School', backref='teachers') 

Luego agrego una propiedad híbrida al maestro que usa la relación, como:

 @hybrid_property def school_name(self): return self.school.name 

Y esa propiedad funciona bien cuando la uso como teacher_instance.school_name . Sin embargo, también me gustaría hacer consultas como Teacher.query.filter(Teacher.school_name == 'x') , pero eso me da un error:

 `AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'school_name'`. 

Siguiendo la documentación de SQLAlchemy, agregué una expresión híbrida simple, como la siguiente:

 @school_name.expression def school_name(cls): return School.name 

Sin embargo, cuando vuelvo a intentar la misma consulta, genera una consulta SQL sin la cláusula de unión, por lo que obtengo todas las filas disponibles en la Escuela, no solo las que coinciden con la clave externa en el Profesor.

De la documentación de SQLAlchemy me di cuenta de que la expresión espera un contexto donde la unión ya está presente, por lo que intenté la consulta nuevamente como:

Teacher.query.join(School).filter(Teacher.school_name == 'x')

Y eso realmente funciona, pero anula el propósito de tratar de obtener el azúcar sintáctico allí, en primer lugar, si necesito conocer el modelo de la Escuela para obtener eso. Supongo que hay una forma de obtener esa unión en la expresión, pero no pude encontrarla en ninguna parte. La documentación tiene un ejemplo con la expresión que devuelve una subconsulta creada directamente con select() , pero incluso eso no funcionó para mí.

¿Algunas ideas?

ACTUALIZAR

Después de la respuesta de Eevee a continuación, usé el proxy de asociación como se sugiere y funciona, pero también sentí curiosidad por el comentario de que debería funcionar con la subconsulta Select select() y traté de averiguar qué hice mal. Mi bash original fue:

 @school_name.expression def school_name(cls): return select(School.name).where(cls.id_school == School.id).as_scalar() 

Y resulta que me estaba dando un error porque me perdí la lista en select (). El siguiente código funciona bien:

 @school_name.expression def school_name(cls): return select([School.name]).where(cls.id_school == School.id).as_scalar() 

Un enfoque mucho más simple para un caso simple como este es un proxy de asociación :

 class Teacher(db.Model): school_name = associationproxy('school', 'name') 

Esto admite consultas (al menos con == ) automáticamente.

Tengo curiosidad por saber cómo el ejemplo de select() híbrida select() no funcionó para usted, ya que es la forma más fácil de solucionar esto dentro de un híbrido. Y para completar, también puede usar un transformador para enmendar la consulta directamente en lugar de la subconsulta.