2011-05-16 11 views
5

¿Es posible agregar a una relación SQLAlchemy usando identificadores en lugar de objetos?SQLAlchemy: agregue una relación usando id en lugar de objeto?

Por ejemplo, considere dos clases SQLAlchemy declarativas, revisión y artista, con una relación entre ellos:

class Review(Base): 
    artist_id = Column(Integer, ForeignKey('artist.id')) 
    artist = relationship(Artist, backref=backref('reviews', order_by=id)) 
    # etc. 

class Artist(Base): 
    # etc. 

Con una lista de revisión de ID para añadir a un artista, me parece que tenga que buscar el artista del ello, a continuación, agregar el objeto de artista para la revisión, así:

for review_id in review_ids: 
    review = session.query(Review).filter(Review.id==review_id).first() 
    artist.reviews.append(review) 

estoy seguro de que sería más eficiente para omitir las operaciones de búsqueda y simplemente añadir iDS, pero ¿es esto posible?

Respuesta

6

Su mejor apuesta es, probablemente, para componer una expresión update contra las tablas del forro. De lo contrario, no puede modificar realmente un Review sin consultarlo (y eso es lo que hace, en realidad no está modificando el Artist).

Suponiendo Review.id es la clave principal, que sería más o menos ser:

conn = session.connection() 
conn.execute(Review.__table__ 
       .update() 
       .values(artist_id=artist_id) 
       .where(Review.id.in_(review_ids)) 
      ) 
+0

Brillante, gracias. –

1

No estoy seguro de haber entendido. Creo que se desea algo como esto:

reviews = session.query(Review).filter(Review.id.in_(review_ids)).all() 

artist.reviews.extend(reviews) 
+0

En realidad eso es lo que estoy haciendo! Escribí el código anterior para proporcionar un ejemplo más simple. Todavía está buscando un objeto de revisión para cada inserción, que estoy tratando de evitar. Aunque gracias por tu sugerencia. –

3

Creo que si desea seguir con la solución ORM pura, usted tiene que vivir con el patrón de consulta algo ineficaz.

@TokenMacGuy ha proporcionado una buena alternativa. Puede integrar ese enfoque agregando add_reviews() a la clase Artist(). Esto aumentaría la api de orm "estándar", por lo que podría usar cualquiera dependiendo de la situación.

from sqlalchemy.orm.session import object_session 

class Artist(Base): 
    def add_reviews(self, review_ids): 
     sess = object_session(self) 
     if isinstance(review_ids, int): review_ids = [review_ids] 
     sess.execute(
      Review.__table__ 
      .update() 
      .values(artist_id=self.artist_id) 
      .where(Review.id.in_(review_ids)) 
     ) 
     sess.refresh(self) 

review_ids = [123, 556, 998, 667, 111] 
artist.add_reviews(review_ids) 
review_id = 333 
artist.add_reviews(review_id) 
Cuestiones relacionadas