Hi Michael,
I'm guilty of two over-simplifications in the code used in my example...
Firstly, the substring property/column (with which I had a problem) applies
to a subclass (using "joined table inheritance") and the variable to which
it applies is specified in its parent class. Hence, I started by assuming
that I'd need something along the lines of:
class Parent(Base):
my_string
class Child(Parent):
....
@classproperty/@property/ some other decorator
def my_substr(cls):
return column_property ( .... cls.my_string .... )
However, trying this (ie the classproperty/column_property within Child),
returned <sqlalchemy.orm.properties.ColumnProperty object ...> (the error
I referred to in my original question)
I'm confused about why I'm not able to get this (or some variation of it) to
work. Is this indeed possible?
Looking at the documentation (as a consequence of the error), my I was drawn
to the syntax used in the section on 'mixins' (ie, the column_property
defined externally).
My second over-simplification regards the the function itself. The function
I'm trying to use [which I'm aware doesn't translate easily to sqlite], is:
func.substr(cls.my_str, func.instr(cls.my_str, " ")+1, 2)
Now, thanks to your response, I now actually have the following *working*
(using mysql):
class MySubStr(object):
@classproperty
def my_substr(cls):
return column_property(
func.substr(cls.my_string, func.instr(cls.my_string,
" ")+1, 2)
)
However, replacing:
func.substr(cls.my_string, func.instr(cls.my_string, " ")+1, 2)
with (in order to attach a label to the column):
select([func.substr(cls.my_string, func.instr(cls.my_string, " ")+1,
2)]).label('exch_code')
Gives me -- AttributeError: 'NoneType' object has no attribute '_keymap'
(full traceback below).
Apologies for my earlier over-simplification (and my late response!). And I
hope that what I've responded with is clear!!
Regards,
Rob
-------------------------------------------------------------------------------------------------------------------------
/home/robertsudwarts/tg2env/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6.egg/sqlalchemy/orm/query.pyc
in one(self)
1520
1521 """
-> 1522 ret = list(self)
1523
1524 l = len(ret)
/home/robertsudwarts/tg2env/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6.egg/sqlalchemy/orm/query.pyc
in instances(self, cursor, _Query__context)
1667 break
1668 else:
-> 1669 fetch = cursor.fetchall()
1670
1671 if custom_rows:
/home/robertsudwarts/tg2env/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6.egg/sqlalchemy/engine/base.pyc
in fetchall(self)
2381
2382 try:
-> 2383 l = self.process_rows(self._fetchall_impl())
2384 self.close()
2385 return l
/home/robertsudwarts/tg2env/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6.egg/sqlalchemy/engine/base.pyc
in process_rows(self, rows)
2364 process_row = self._process_row
2365 metadata = self._metadata
-> 2366 keymap = metadata._keymap
2367 processors = metadata._processors
2368 if self._echo:
AttributeError: 'NoneType' object has no attribute '_keymap'
On 2 August 2010 19:42, Michael Bayer <[email protected]> wrote:
>
> On Aug 2, 2010, at 1:40 PM, Michael Bayer wrote:
>
> >
> > On Aug 2, 2010, at 12:19 PM, Robert Sudwarts wrote:
> >
> >> Hi,
> >>
> >> I'm having trouble understanding the correct syntax to be used with
> Declarative and a column property.
> >> The select statement I'm using is:
> select([func.substr(my_table.c.my_string, 2, 3)]).label(my_substr'),
> deferred=True
> >> And (as per the docs using the expanded syntax, this works as expected.
> >>
> >> With the Declarative syntax, I've tried:
> >>
> >> from sqlalchemy.util import classproperty
> >> from sqlalchemy.orm ..., column_property
> >>
> >> class MySubstr(object):
> >> @classproperty
> >> def my_substr(cls):
> >> return column_property(
> >>
> select([func.substr(cls.my_str, 2, 3)]).label('my_substr')
> >> )
> >>
> >> class MyTable(Base, MySubstr):
> >> .....
> >>
> >> and then expect to be able to call a record in MyTable and return its
> "my_substr", however, all I'm getting is a representation of the object ...
> >> eg <sqlalchemy.orm.properties.ColumnProperty object at 0xa4951cc> and
> no apparent way of seeing its value.
> >
>
> oh and also, you don't need the select() here either:
>
> class MyTable(Base):
> __tablename__ = 'foo'
> id = Column(Integer, primary_key=True)
> my_str = Column('my_str', String)
> my_substr = column_property(func.substr(cls.my_str, 2, 3))
>
>
>
>
> > I see nothing wrong with the example, the only potential glitch is that
> "my_str" needs to have a name assigned up front. You didn't illustrate that
> part here, so FYI it would be extremely helpful if you could attach fully
> working examples. In this case the example is:
> >
> > from sqlalchemy import *
> > from sqlalchemy.ext.declarative import declarative_base
> > from sqlalchemy.util import classproperty
> > from sqlalchemy.orm import column_property, sessionmaker
> >
> > Base = declarative_base()
> >
> > engine = create_engine('sqlite://', echo=True)
> >
> > class MySubstr(object):
> > @classproperty
> > def my_substr(cls):
> > return column_property(
> > select([func.substr(cls.my_str, 2,
> 3)]).label('my_substr')
> > )
> >
> > class MyTable(Base, MySubstr):
> > __tablename__ = 'foo'
> > id = Column(Integer, primary_key=True)
> > my_str = Column('my_str', String)
> >
> >
> > Base.metadata.create_all(engine)
> >
> > sess = sessionmaker(engine)()
> > m1 = MyTable(my_str='some string')
> > sess.add(m1)
> > sess.commit()
> >
> > print m1.my_substr
> >
> > and it works fine.
> >
> >
> >
> >>
> >> Should the @classproperty sit within the "MyTable(Base)" itself (ie is
> there a need for the separate object --
> >
> > @classproperty is typically specific to the mixin use case, which is why
> its only discussed in the "mixins" section of the declarative documentation.
> It's a useful construct in other situations but you certainly don't need it
> if you aren't using mixins.
> >
> >
> >> and have I been confused by the section on 'mixins' )?
> >
> > I'm not sure why you're choosing to use a mixin here, as your
> column_property appears to be pretty specific to the MyTable class. if the
> documentation led you to believe that you needed one, I am extremely curious
> why that is the case as mixins are absolutely optional and that would be a
> serious documentation bug. Without the mixin, it is:
> >
> > class MyTable(Base):
> > __tablename__ = 'foo'
> > id = Column(Integer, primary_key=True)
> > my_str = Column('my_str', String)
> > my_substr = column_property(
> > select([func.substr(my_str, 2,
> 3)]).label('my_substr')
> > )
> >
> >
> >
> > --
> > 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]<sqlalchemy%[email protected]>
> .
> > 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 [email protected].
> To unsubscribe from this group, send email to
> [email protected]<sqlalchemy%[email protected]>
> .
> 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 [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.