A few days ago I asked what appears in the body of the message, a few
lines below. To summarize:

Let's say I have a class "User" (yeah, to define "users" in my
application) and each user can belong to one "UserGroup" (another
class of my application). The User class would be something like:


class User(declarativeBase):
        """Represents a user"""
        __tablename__ = "users"

        _id = Column("id", Integer, primary_key=True)
        _firstName = Column("first_name", String(50))
        _lastName = Column("last_name", String(50))
        _userName = Column("user_name", String(50), unique=True, nullable=False)
        _password = Column("password", String(64), nullable=False)
        _userGroupId = Column("user_group_id", Integer, 
ForeignKey("user_groups.id"))

        _userGroup = relationship("UserGroup", uselist=False)


        id = synonym('_id', descriptor=property(getId, setId))
        firstName = synonym('_firstName', descriptor=property(getFirstName,
                                        setFirstName))
        lastName = synonym('_lastName', descriptor=property(getLastName, 
setLastName))
        userName = synonym('_userName', descriptor=property(getUserName, 
setUserName))
        password = synonym('_password', descriptor=property(getPassword, 
setPassword))
        userGroupId = synonym('_userGroupId',
                                        descriptor=property(getUserGroupId, 
setUserGroupId))
        userGroup = synonym('_userGroup', descriptor=property(getUserGroup,
                                        setUserGroup))

I wanted to find a way to find which synonyms "pointed" to foreign
keys and which ones pointed to relationships. Basically, having a
couple of methods like the following:
     def getRelationships(cls):
that when invoked with getRelationships(User.User) would return a list
with ["userGroup"] (withouth the "_" in front)
and another:
     def getForeignKeys(cls):
that would return ["userGroupId"]

So far I've done this:

def getRelationships(cls):
        retval = list()
        mapper = sqlalchemy.orm.class_mapper(cls)
        actualNameToSynonym = dict()
        relationships = set()

        for prop in mapper.iterate_properties:
                if isinstance(prop, sqlalchemy.orm.properties.SynonymProperty):
                        actualNameToSynonym[prop.name] = prop.key
                        # dictionary <_userName, userName, userGroup, 
_userGroup>

                elif isinstance(prop, 
sqlalchemy.orm.properties.RelationshipProperty):
                        relationships.add(prop.key)
                        #set with _userGroup, and rest of relationships

        for relationship in relationships:
                retval.append(actualNameToSynonym[relationship])

        return retval

def getForeignKeys(cls):
        retval = list()
        mapper = sqlalchemy.orm.class_mapper(cls)
        actualNameToSynonym = dict()
        columnsWithForeignKeys = set()

        for prop in mapper.iterate_properties:
                if isinstance(prop, sqlalchemy.orm.properties.SynonymProperty):
                        actualNameToSynonym[prop.name] = prop.key
                        # dictionary <_userName, userName, userGroup, 
_userGroup>

                elif isinstance(prop, sqlalchemy.orm.properties.ColumnProperty):
                        for column in prop.columns:
                                if len(column.foreign_keys) > 0:
                                        columnsWithForeignKeys.add(prop.key)

        for columnWithForeignKeys in columnsWithForeignKeys:
                retval.append(actualNameToSynonym[columnWithForeignKeys])
        return retval

Both are very similar: First they create a dictionary mapping the
synonym's key with the "real" name (<_userGroup, userGroup>) and store
the "relationships" or the columns that have a "foreign key" in a set
(for the method that tries to get relationships, that set would be
set("_userGroup") and for the one that tries to get foreign keys,
set("_userGroupId")) . In a second "for" loop they match that
"underscored" name with the name of the synonym to return a list with
the names of the synonyms, and not the actual columns (basically, to
transform "_userGroupId" to "userGroupId")

They seem to work, at least with my not-complicated-at-all classes,
but I'd like to know what do you guys think of my approach. Is it
good? Can it break something? Is there a better way?

Thank you!



2011/2/18 Hector Blanco <white.li...@gmail.com>:
> I'll give it a try!!
>
> Thank you!
>
> 2011/2/18 Michael Bayer <mike...@zzzcomputing.com>:
>>
>> On Feb 17, 2011, at 6:37 PM, Hector Blanco wrote:
>>
>>> Hello everyone!
>>>
>>> Let's say I have a class defined like this:
>>>
>>> class User(declarativeBase):
>>>       """Represents a user"""
>>>       __tablename__ = "users"
>>>
>>>       _id = Column("id", Integer, primary_key=True)
>>>       _phone = Column("phone", String(16))
>>>       _userName = Column("user_name", String(50), unique=True, 
>>> nullable=False)
>>>       _password = Column("password", String(64), nullable=False)
>>>
>>>       _userGroupId = Column("user_group_id", Integer, 
>>> ForeignKey("user_groups.id"))
>>>       _userGroup = relationship("UserGroup", uselist=False)
>>>
>>>       def setId(self, id):
>>>               """Set id"""
>>>               self._id = int(id)
>>>
>>>       def getId(self):
>>>               """Get id"""
>>>               return self._id
>>>
>>>       def setUserGroupById(self, userGroupId):
>>>               userGroupId = int(userGroupId)
>>>               if userGroupId != self.userGroupId:
>>>                       self.userGroup = UserGroupManager.getById(userGroupId)
>>>
>>>       def setUserGroup(self, userGroup):
>>>               """Set user group"""
>>>               if isinstance(userGroup, UserGroup):
>>>                       self._userGroup = userGroup
>>>               else:
>>>                       raise TypeError("Trying to set a " + 
>>> str(type(userGroup)) + " as user group")
>>>
>>>       def getUserGroup(self):
>>>               """Get user"""
>>>               return self._userGroup
>>>
>>>       #More getters/setters
>>>
>>>       id = sqlalchemy.orm.synonym('_id', descriptor=property(getId, setId))
>>>       phone = sqlalchemy.orm.synonym('_phone',
>>> descriptor=property(getPhone, setPhone))
>>>       userName = sqlalchemy.orm.synonym('_userName',
>>> descriptor=property(getUserName, setUserName))
>>>       password = sqlalchemy.orm.synonym('_password',
>>> descriptor=property(getPassword, setPassword))
>>>       userGroupId = sqlalchemy.orm.synonym('_userGroupId',
>>> descriptor=property(getUserGroup, setUserGroup))
>>>       userGroup = sqlalchemy.orm.synonym('_userGroup',
>>> descriptor=property(getUserGroup, setUserGroup))
>>>
>>> I have created an utility that, given an instance gives me the names
>>> of the synonyms in said instance.
>>>
>>> def getProperties(instance):
>>>       properties = list()
>>>       mapper = sqlalchemy.orm.object_mapper(instance)
>>>       for prop in mapper.iterate_properties:
>>>               if isinstance(prop, 
>>> sqlalchemy.orm.properties.SynonymProperty):
>>>                       properties.append(prop.key)
>>>       return properties
>>>
>>> That would give me ["id", "phone", "userName", "password",
>>> "userGroupId", "userGroup"], so I can more or less generically go
>>> through all said values and execute things like
>>>
>>> for attribute in getProperties(instanceOfUser):
>>>     value = getattr(instanceOfUser, attribute)
>>>
>>> Is there any way of knowing that said "value"s are ForeignKeys or
>>> relationships? For instance, I'd like to know that the attribute "id"
>>> is a regular (well... kind of regular... it's a Primary key, but it's
>>> not going to point to anything in another table) numeric attribute,
>>> but "userGroupId" is a foreign key and "userGroup" is a Relationship.
>>> I've been sneaking in the vars, __dict__, dir of the values returned
>>> by getattr, but I haven't been able to find anything suitable.
>>
>>
>> you just have to poke around and use isinstance() on the MapperProperty 
>> objects, and/or check for known attributes.    The choices are 
>> ColumnProperty, RelationshipProperty, SynonymProperty, etc.
>>
>> synonyms are also superceded in 0.7.  they're not very useful compared to 
>> hybrids.
>>
>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> sqlalchemy+unsubscr...@googlegroups.com.
>> 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 sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to