On 10/14/2010 01:30 PM, Chris Withers wrote:
> Hi All,
>
> I currently have code that looks like this:
>
> recipients = []
> if recipient_ids:
>    for id in recipient_ids.split(','):
>       recipients.append(
>           session.query(recipient.Recipient).filter_by(id=id).one()
>       )
> else:
>     recipient_ids = ()
> feed.recipients = recipients
>
> Where the models are:
>
> feed_recipient = Table('feed_recipient', Base.metadata,
>     Column('feed_id', String(length=32), ForeignKey('feed.id')),
>     Column('recipient_id', Integer, ForeignKey('recipient.id')),
>     )
>
> class Feed(Base):
>     __tablename__ = 'feed'
>     id = Column(String(length=32), primary_key=True)
>     recipients = relation('Recipient', secondary=feed_recipient)
>
> class Recipient(Base,ComputedMapperArgs):
>     __tablename__='recipient'
>     feeds = relation('Feed', secondary=feed_recipient)
>
> It feels like a horribly inefficient way of updating the many-to-many
> relationship. I guess I could just use the sql abstraction layer, but
> that feels like circumventing the ORM without just cause ;-)
>
> Am I missing something? If I have a sequence of ids where I want to
> update the many to many relationship as above, what's the best way of
> doing it?

You can at least reduce it to a single query:

recipient_id_list = recipient_ids.split(',')
q = session.query(recipient.Recipient)
q = q.filter(recipient.Recipient.id.in_(recipient_id_list))
recipients = q.all()
if len(recipients) != len(recipient_id_list):
    invalid_ids = (set(recipient_id_list)
                   - set(x.id for x in recipients))
    raise StandardError("Invalid recipient ids: %s" % sorted(invalid_ids))
feed.recipients = recipients

I wish there was an easy way to do, say:

feed.recipients.ids = recipient_id_list

which would let you avoid querying at all. The downside is you won't
notice invalid ids until the next flush(). Alternatively, you could also
accomplish this via:

feed.recipients = [session.merge(recipient.Recipient(id=id), load=False)
                   for id in recipient_id_list]

if session.merge() allowed you to merge newly-created transient objects
with load=False. Maybe add a "force" parameter to merge, to tell
SQLAlchemy that you really know what you are doing?

-Conor

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to