allow non-property objects to work with declarative string resolution

Issue #2761 resolved
Mike Bayer repo owner created an issue
from sqlalchemy import Column, Integer, String, ForeignKey, case
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    firstname = Column(String(50))
    lastname = Column(String(50))
    game_id = Column(Integer, ForeignKey('game.id'))

    @hybrid_property
    def fullname(self):
        if self.firstname is not None:
            return self.firstname + " " + self.lastname
        else:
            return self.lastname

    @fullname.expression
    def fullname(cls):
        return case([           (cls.firstname != None, cls.firstname + " " + cls.lastname),
        ](
), else_=cls.lastname)


class Game(Base):
    __tablename__ = 'game'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    users = relationship("User", order_by="User.fullname")

if __name__ == '__main__':
    game = Game(name="tetris")

patch:

diff --git a/lib/sqlalchemy/ext/declarative/clsregistry.py b/lib/sqlalchemy/ext/declarative/clsregistry.py
index 95aba93..a669e37 100644
--- a/lib/sqlalchemy/ext/declarative/clsregistry.py
+++ b/lib/sqlalchemy/ext/declarative/clsregistry.py
@@ -12,7 +12,7 @@ This system allows specification of classes and expressions used in
 from ...orm.properties import ColumnProperty, RelationshipProperty, \
                             SynonymProperty
 from ...schema import _get_table_key
-from ...orm import class_mapper
+from ...orm import class_mapper, interfaces
 from ... import util
 from ... import exc
 import weakref
@@ -190,19 +190,21 @@ class _GetColumns(object):
     def __getattr__(self, key):
         mp = class_mapper(self.cls, configure=False)
         if mp:
-            if not mp.has_property(key):
+            if key not in mp.all_orm_descriptors:
                 raise exc.InvalidRequestError(
                             "Class %r does not have a mapped column named %r"
                             % (self.cls, key))

-            prop = mp.get_property(key)
-            if isinstance(prop, SynonymProperty):
-                key = prop.name
-            elif not isinstance(prop, ColumnProperty):
-                raise exc.InvalidRequestError(
-                            "Property %r is not an instance of"
-                            " ColumnProperty (i.e. does not correspond"
-                            " directly to a Column)." % key)
+            desc = mp.all_orm_descriptors[key](key)
+            if desc.extension_type is interfaces.NOT_EXTENSION:
+                prop = desc.property
+                if isinstance(prop, SynonymProperty):
+                    key = prop.name
+                elif not isinstance(prop, ColumnProperty):
+                    raise exc.InvalidRequestError(
+                                "Property %r is not an instance of"
+                                " ColumnProperty (i.e. does not correspond"
+                                " directly to a Column)." % key)
         return getattr(self.cls, key)

Comments (2)

  1. Log in to comment