On Aug 21, 2012, at 5:47 PM, Sergey V. wrote:

> Hi all,
> 
> I've asked this question on stackoverflow: 
> http://stackoverflow.com/questions/12031861/sqlalchemy-how-do-i-get-an-object-from-a-relationship-by-objects-pk/12032405
> 
> Basically, I'm looking for a dict-like access to a relationship to be able to 
> quickly retrieve items by some key (item's PK). To illustrate, a "normal" 
> relationship is list-like:
> 
>     for book in library.books:
>         print book.id  # prints 10, 20, 30
> 
> In addition, I'd like to be able to access "books" from an already-loaded 
> relationship by their id:
> 
>     book1 = library.books.by_id(10)
>     book2 = library.books.by_id(20)
>     book3 = library.books.by_id(23)  # raises KeyError
> 
> while still being able to iterate over library.books in a list-like manner.
> 
> I'm looking at MappedCollection 
> (http://docs.sqlalchemy.org/en/latest/orm/collections.html?highlight=collection#custom-dictionary-based-collections)
>  - would building a custom collection class be the right solution to the 
> problem? Or is there something pre-built for this purpose in the depths of 
> SQLAlchemy?

there's two variations here.   One, which is definitely the quickest, is just 
to use a @property that re-evaulates library.books as a dict:

@property
def books_by_id(self):
    return dict((book.id, book) for book in self.books)

the other, the more "integrated" approach, is to use a collection_class that's 
mostly a dict but just yields the values instead of the keys when iterated.   
It might be nice if attribute_mapped_collection provided a simple argument to 
pass in a "dict" subclass but apparently it doesn't have this yet, so just 
subclass MappedCollection:

class IterateValuesDict(MappedCollection):
    def __iter__(self):
        return iter(self.values())

collection_cls = lambda: IterateValuesDict(keyfunc=lambda obj: obj.id)

class Library(Base):
    # ...
    books = relationship(Book, collection_cls=collection_cls)




> 
> Thanks,
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To view this discussion on the web visit 
> https://groups.google.com/d/msg/sqlalchemy/-/mUIFlVguh34J.
> To post to this group, send email to sqlalchemy@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.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@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