determine if relationship is a backref

57 views
Skip to first unread message

Jason

unread,
Aug 15, 2012, 11:35:39 AM8/15/12
to sqlal...@googlegroups.com
Is there a way to determine if a relationship property on a model class is a backref?

For instance I have the model:

class Department(Base):
    department_id = Column(Int(), primary_key=True)

class Employee(Base):
    employee_id = Column(Int(), primary_key=True)
    department_id = Column(Int(), ForeignKey(Department.deptartment_id), nullable=False)
    department = relationship(Department, backref='employees')

I'm looping through the attributes of each table and for each attribute that has a relationship property I want to determine whether the relationship constructor was called on the current table or not. So for Department.employees it would be False because the relationship was defined as a backref from another table. Is there a method/technique to accomplish this?


Thanks,

Jason

Michael Bayer

unread,
Aug 15, 2012, 11:41:20 AM8/15/12
to sqlal...@googlegroups.com

On Aug 15, 2012, at 11:35 AM, Jason wrote:

> Is there a way to determine if a relationship property on a model class is a backref?

not in the strict sense, because a "backref" is just configurational sugar for two separate relationship() objects that are aware of each other. But you can determine one of those relationship() objects given the other one.

>
> For instance I have the model:
>
> class Department(Base):
> department_id = Column(Int(), primary_key=True)
>
> class Employee(Base):
> employee_id = Column(Int(), primary_key=True)
> department_id = Column(Int(), ForeignKey(Department.deptartment_id), nullable=False)
> department = relationship(Department, backref='employees')
>
> I'm looping through the attributes of each table and for each attribute that has a relationship property I want to determine whether the relationship constructor was called on the current table or not. So for Department.employees it would be False because the relationship was defined as a backref from another table. Is there a method/technique to accomplish this?

in this case it seems like you aren't as much concerned about the actual mapper configuration as you are about codepaths being invoked. So we "instrument" functions to track when they are called.

You'd make a wrapper around relationship() yourself, which would be used by userland code. This allows userland relationship() calls to be distinguished from those that SQLAlchemy calls itself internally:

from sqlalchemy.orm import relationship as _relationship
relationships_called = set()
def relationship(*arg, **kw):
rel = _relationship(*arg, **kw)
relationships_called.add(rel)
return rel

def was_relationship_called(rel):
return rel in relationships_called


Jason

unread,
Aug 15, 2012, 2:00:39 PM8/15/12
to sqlal...@googlegroups.com


On Wednesday, August 15, 2012 11:41:20 AM UTC-4, Michael Bayer wrote:



in this case it seems like you aren't as much concerned about the actual mapper configuration as you are about codepaths being invoked.   So we "instrument" functions to track when they are called.

You'd make a wrapper around relationship() yourself, which would be used by userland code.  This allows userland relationship() calls to be distinguished from those that SQLAlchemy calls itself internally:

from sqlalchemy.orm import relationship as _relationship
relationships_called = set()
def relationship(*arg, **kw):
    rel = _relationship(*arg, **kw)
    relationships_called.add(rel)
    return rel

def was_relationship_called(rel):
    return rel in relationships_called


That's so simple I didn't think of it. I may switch from what I ended up doing. I check if the relationship column with the foreign key is on the same table as this relationship property. This works because by convention I put the relationship on the same table as the FK column and I am working on a CRUD that automatically adds relationships to forms only if they can be displayed as a simple select list (a relationship that did not have an FK on it's model class would need a more advanced interface).

# prop is a RelationshipProperty
for pair in prop.local_remote_pairs:
    for el in pair:
        for fk in el.foreign_keys:
            if fk.parent.table == MyModel.__table__:
                local = True 

Thanks for the help,

Jason
Reply all
Reply to author
Forward
0 new messages