the typical hook for this kind of thing is __declare_last__, works after 
everything has been compiled.

you might have an easier time also (or might not matter) if you build against 
the Table (i.e. Foo.__table__.alias(), etc.) instead of firing up the class 
with aliased(Foo), but if you're in __declare_last__ might not matter anyway.


On Mar 18, 2013, at 12:20 PM, millerdev <miller...@gmail.com> wrote:

> Hi,
> 
> Using declarative here, and I'm trying to create a column_property with a 
> correlated subquery that returns a count of records with a matching value in 
> some other column. Here's what I've tried. Option 1 is the best, option 2 is 
> ugly but second best, option 3 is not a good option since there are many 
> other classes involved and the place where I'd need to put that code is far 
> away from where it logically belongs.
> 
> from sqlalchemy import *
> from sqlalchemy.orm import *
> from sqlalchemy.ext.declarative import *
> from sqlalchemy.ext.declarative import declared_attr
> 
> Base = declarative_base()
> option = 1
> 
> class Foo(Base):
>     __tablename__ = 'foo'
>     id = Column(Integer, primary_key=True)
>     bar_id = Column(Integer, ForeignKey("bar.id"))
>     name = Column(String)
> 
>     if option == 1:
>         # does not work (see first traceback below)
>         @declared_attr
>         def name_count(cls):
>             clx = aliased(cls)
>             return column_property(
>                 select(func.count([clx.id]))
>                     .where(clx.name == cls.name)
>                     .correlate(cls.__table__))
> 
> if option == 2:
>     # does not work (see second traceback below)
>     _foo = aliased(Foo)
>     Foo.name_count = column_property(
>             select([func.count(_foo.id)])
>                 .where(_foo.name == Foo.name)
>                 .correlate(Foo.__table__))
> 
> 
> class Bar(Base):
>     __tablename__ = 'bar'
>     id = Column(Integer, primary_key=True)
>     name = Column(String)
> 
> 
> if option == 3:
>     # works, but really not where I want to put this code
>     _foo = aliased(Foo)
>     Foo.name_count = column_property(
>             select([func.count(_foo.id)])
>                 .where(_foo.name == Foo.name)
>                 .correlate(Foo.__table__))
> 
> 
> Option 1 traceback:
> 
> Traceback (most recent call last):
>   File "temp/example.py", line 8, in <module>
>     class Foo(Base):
>   File ".../python2.7/site-packages/sqlalchemy/ext/declarative.py", line 
> 1348, in __init__
>     _as_declarative(cls, classname, cls.__dict__)
>   File ".../python2.7/site-packages/sqlalchemy/ext/declarative.py", line 
> 1181, in _as_declarative
>     value = getattr(cls, k)
>   File ".../python2.7/site-packages/sqlalchemy/ext/declarative.py", line 
> 1554, in __get__
>     return desc.fget(cls)
>   File "temp/example.py", line 15, in name_count
>     clx = aliased(cls)
>   File ".../python2.7/site-packages/sqlalchemy/orm/util.py", line 385, in 
> aliased
>     return AliasedClass(element, alias=alias, name=name, 
> adapt_on_names=adapt_on_names)
>   File ".../python2.7/site-packages/sqlalchemy/orm/util.py", line 298, in 
> __init__
>     self.__mapper = _class_to_mapper(cls)
>   File ".../python2.7/site-packages/sqlalchemy/orm/util.py", line 673, in 
> _class_to_mapper
>     raise exc.UnmappedClassError(class_or_mapper)
> sqlalchemy.orm.exc.UnmappedClassError: Class '__main__.Foo' is not mapped
> 
> 
> Option 2 traceback:
> 
> Traceback (most recent call last):
>   File "temp/example.py", line 16, in <module>
>     select([func.count(_foo.id)])
>   File ".../python2.7/site-packages/sqlalchemy/sql/expression.py", line 1229, 
> in __call__
>     return func(*c, **o)
>   File ".../python2.7/site-packages/sqlalchemy/sql/functions.py", line 16, in 
> __call__
>     args = [_literal_as_binds(c) for c in args]
>   File ".../python2.7/site-packages/sqlalchemy/sql/expression.py", line 1440, 
> in _literal_as_binds
>     return element.__clause_element__()
>   File ".../python2.7/site-packages/sqlalchemy/orm/attributes.py", line 117, 
> in __clause_element__
>     return self.comparator.__clause_element__()
>   File ".../python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 
> 506, in oneshot
>     result = self.fget(obj, *args, **kw)
>   File ".../python2.7/site-packages/sqlalchemy/orm/properties.py", line 156, 
> in __clause_element__
>     return self.adapter(self.prop.columns[0])
>   File ".../python2.7/site-packages/sqlalchemy/orm/util.py", line 334, in 
> __adapt_element
>     return self.__adapter.traverse(elem).\
>   File ".../python2.7/site-packages/sqlalchemy/sql/visitors.py", line 185, in 
> traverse
>     return replacement_traverse(obj, self.__traverse_options__, replace)
>   File ".../python2.7/site-packages/sqlalchemy/sql/visitors.py", line 281, in 
> replacement_traverse
>     obj = clone(obj, **opts)
>   File ".../python2.7/site-packages/sqlalchemy/sql/visitors.py", line 270, in 
> clone
>     newelem = replace(elem)
>   File ".../python2.7/site-packages/sqlalchemy/sql/visitors.py", line 182, in 
> replace
>     e = v.replace(elem)
>   File ".../python2.7/site-packages/sqlalchemy/sql/util.py", line 720, in 
> replace
>     return self._corresponding_column(col, True)
>   File ".../python2.7/site-packages/sqlalchemy/sql/util.py", line 695, in 
> _corresponding_column
>     require_embedded=require_embedded)
>   File ".../python2.7/site-packages/sqlalchemy/sql/expression.py", line 2492, 
> in corresponding_column
>     if self.c.contains_column(column):
>   File ".../python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 
> 485, in __get__
>     obj.__dict__[self.__name__] = result = self.fget(obj)
>   File ".../python2.7/site-packages/sqlalchemy/sql/expression.py", line 2558, 
> in columns
>     self._populate_column_collection()
>   File ".../python2.7/site-packages/sqlalchemy/sql/expression.py", line 3704, 
> in _populate_column_collection
>     col._make_proxy(self)
>   File ".../python2.7/site-packages/sqlalchemy/schema.py", line 1103, in 
> _make_proxy
>     fk = [ForeignKey(f.column) for f in self.foreign_keys]
>   File ".../python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 
> 485, in __get__
>     obj.__dict__[self.__name__] = result = self.fget(obj)
>   File ".../python2.7/site-packages/sqlalchemy/schema.py", line 1392, in 
> column
>     tname)
> sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 
> 'foo.bar_id' could not find table 'bar' with which to generate a foreign key 
> to target column 'id'
> 
> 
> It looks like the problem is that mapper state is not being initialized 
> properly prior to setting up the column_property in the first two options. Is 
> there another type of property similar to declared_attr that will allow me to 
> add the column_property some place in the initialization sequence where 
> mappers have been sufficiently initialized to allow constructing a select 
> statement?
> 
> ~ Daniel
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>  
>  

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


Reply via email to