2008-11-06 7 views
8

Estoy usando SQLAlchemy 0.5rc, y me gustaría agregar un filtro automático a una relación, de modo que cada vez que intente obtener registros para esa relación, ignore los "remotos" si están marcados como "logically_deleted" (un campo booleano de la tabla secundaria)¿Cómo agregar un filtro automático a una relación con SQLAlchemy?

Por ejemplo, si un objeto "primario" tiene una relación "secundarios" que tiene 3 registros, pero uno de ellos se elimina lógicamente, cuando consulto " Padre "Me gustaría que SQLA llene el objeto primario con solo dos hijos.
¿Cómo debo hacerlo? Al agregar una condición "y" al parámetro primaryjoin de la relación? (Por ejemplo, "Children.parent_id == Parent.id and Children.logically_deleted == False", pero ¿es correcto escribir "y" de esta manera?)

Editar:
logré hacerlo de esta manera

children = relation("Children", primaryjoin=and_(id == Children.parent_id, Children.logically_deleted==False)) 

pero hay una manera de para usar una cadena como primaryjoin en su lugar?

Respuesta

3

La función and_() es la forma correcta de hacer las conjunciones lógicas en SQLAlchemy, junto con el operador &, pero tenga cuidado con este último ya que tiene reglas de precedencia sorprendentes, es decir, mayor precedencia que los operadores de comparación.

También podría usar una cadena como unión primaria con el constructor de texto(), pero eso hará que su código se rompa con cualquier alias de tabla que viene con eagerloading y joins.

Para borrado lógico, tal vez sería mejor para mapear toda la clase a través de una selección que hace caso omiso de los valores borrados:

mapper(Something, select([sometable], sometable.c.deleted == False)) 
+0

¿Se puede traducir esto utilizando __mapper_args__? Quiero decir que estoy usando declarativo. – Marconi

+0

Intenté usarlo en mapper_args, pero recibí un mensaje de error que decía "mapper() obtuvo varios valores para el argumento de palabra clave 'local_table'". Entonces me temo que es inútil. –

0

sólo estoy actualmente en desarrollo agains 0.4.something, pero así es como me gustaría sugerir que:

db.query(Object).filter(Object.first==value).filter(Object.second==False).all() 

creo que eso es lo que está tratando de hacer, ¿verdad?

(Nota: escrito en un navegador web, no código real!)

+0

No, estaba buscando algo automático ... aclararé la pregunta :) ¡Gracias! – Joril

+0

Sin preocupaciones. Creo que entiendo lo que estás tratando de hacer, ¡pero principalmente estoy leyendo el código que me diste! –

6

pero ¿hay una manera de utilizar una cadena como primaryjoin en su lugar?

Usted puede usar la siguiente:

children = relationship("Children", primaryjoin="and_(Parent.id==Children.parent_id, Children.logically_deleted==False)" 

Esto funcionó para mí!

Cuestiones relacionadas