On Jan 5, 2013, at 7:42 AM, Alexander Jacob wrote:
> @compiles(i18NColumnClause)
> def compile_i18n_column_clause(element, compiler, **kw):
> return '%s_%s' % (element.name, GLOBAL_LANGUAGE)
>
> # custom type
> class i18NType(sqlalchemy.types.TypeDecorator):
> impl = sqlalchemy.types.Unicode
> def column_expression(self, colexpr):
> return i18NColumnClause(colexpr)
>
> # test class for custom type
> class Country(Base):
>
> __tablename__ = 'country'
> id = Column(Integer, primary_key=True)
> iso2 = Column(String(2))
> name = Column(i18NType(64))
>
> def __repr__(self):
> return "<Country(%d/%s/%s)>" % (self.id, self.iso2, self.name)
>
Interesting approach with the column_expression(), though that seems like it
would circumvent the labeling behavior of the compiler and cause more complex
expressions to fail. The INSERT case might work if you also implemented
bind_expression() but I'm not sure if that approach overall doesn't break too
much of the existing compilation functionality.
A more direct route with @compiles would be to compile Column, but still
tricky, in particular that the compilation process for a Column is very
involved. At the very least, for that to work it would have to be like this:
class i18NColumn(Column): # note it has to be Column, not ColumnClause
pass
@compiles(i18NColumn)
def compile(element, compiler, **kw):
text = compile.visit_column(element, **kw)
text = text.replace(element.name, '%s_%s' %(element.name, GLOBAL_LANGUAGE))
return text
so that existing labeling rules are not circumvented. but even that I'm not
100% sure might not have some gotchas.
Another variant on this would be to use the before_cursor_execute event to just
do a search and replace on the SQL statement before it's passed to the DBAPI, I
sometimes recommend that as well. Giving the "fake" column a name that clearly
indicates internationalization, like Column("name_<i18N>"), is a good way to
give a statement filter a clear path to where those names would go. If you need
this translation behavior everywhere, that might be the best approach.
Though here, there's a less intrusive way to get this behavior if ORM level is
all you need which is by using hybrids:
class Country(Base):
# ...
name_de = Column(String)
name_en = Column(String)
@hybrid_property
def name(self):
return getattr(self, "name_%s" % GLOBAL_LANGUAGE)
@name.setter
def name(self, value):
setattr(self, "name_%s" % GLOBAL_LANGUAGE, value)
the above can be generalized:
def make_hybrid(name):
@hybrid_property
def name_attr(self):
return getattr(self, "%s_%s" % (name, GLOBAL_LANGUAGE))
@name_attr.setter
def name_attr(self, value):
setattr(self, "%s_%s" % (name, GLOBAL_LANGUAGE), value)
name_attr.__name__ = name
return name_attr
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.