On Aug 26, 2013, at 3:43 PM, Florian Rüchel <florian.ruec...@gmail.com> wrote:

> Hey there,
> 
> I have already posted this on stackoverflow but not recieved an answer yet so 
> I thought I might try here. To quote from my original question:

I've seen it, and the issue is that the question is difficult to parse.

> 
> 
> Suppose we have these classes:
> 
>     class Item(Base):
>         id = Column(Integer, primary_key=True)
>         data = Column(String)
>         i18ns = relationship("ItemI18n", backref="item")
> 
>     class ItemI18n(Base):
>         lang_short = Column(String, primary_key=True)
>         item_id = Column(Integer, ForeignKey('item.id'), primary_key=True)
>         name = Column(String)
> [on pastebin]
> 
> 
> The idea here is to have this item's name in multiple languages, for example 
> in English and German. This works fine so far, one can easily work with that. 
> However, most times, I am not interested in all (i.e. both) names but only 
> the users locale.
> 
> For example, if the user is English and wants to have the name in his 
> language, I see two options:
> 
>     # Use it as a list
>     item = session.query(Item).first()
>     print item.data, [i18n.name for i18n in item.i18ns if i18n.lang_short == 
> "en"][0]
> 
>     # Get the name separately
>     item, name = session.query(Item, 
> ItemI18N.name).join(ItemI18N).filter(ItemI18N.lang_short == "en").first()
>     print item.data, name

Based on detail further down, I know what you want, but reading this was 
confusing.   You mean "item" should offer its .name attribute in multiple 
languages, right?   How would that be possible without using a method?  
otherwise how are you instructing the Item object as to what language you'd 
like?

> 
> But business logic is different: I would expect to have an `Item` with a 
> `name` and `description` attribute, so that I would do something like this:
> 
>     item = session.query(Item).first()
>     print item.data, item.name

This doesn't make any sense - where is "description" above?  what does it do?  

> 
> So that's where I want to go: Pull all those attributes from `Item18N` 
> directly into `Item`.

how are you specifying which Item18N you want?   "pulling attributes" is very 
easy and there are several approaches but only if you have the two objects to 
start with.


> And of course, I would have to specify the language anywhere.

where's "anywhere"?  


> 
>         def name(self, locale):


OK here I see we finally have a "name" function with a locale, great !

> 
> But this is not a pretty solution, both because of the overhead of retrieving 
> all I18N data from the database and then fitering that result back to one 
> thus making it completely irrelevant that I pulled all in the first place

Why do you need to retrieve all of the data?  why not just retrieve the one you 
want?

def name(self, locale):
    return 
object_session(self).query(ItemI18N.name).with_parent(self).filter(ItemI18N.locale
 == locale).scalar()

with_parent is one of the helper operators mentioned in the tutorial: 
http://docs.sqlalchemy.org/en/rel_0_8/orm/tutorial.html?highlight=with_parent#common-relationship-operators

if you didn't know about with_parent, this works too:

def name(self, locale):
    return object_session(self).query(ItemI18N.name).filter(self.id == 
ItemI18N.item_id).filter(ItemI18N.locale == locale).scalar()

there are also ways to turn this into a relationship() and use eager loading if 
that helps, slightly less simple.






Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to