On Jun 16, 2012, at 11:41 AM, Michael Bayer wrote:

> 
> It's not a basic question at all as this is a rare edge case, and it's not a 
> "foreign key" by definition.   You need to relate the two tables based on a 
> SQL function, in this case a concatenation.   In some cases this can be 
> tricky, and there's improvements in 0.8 to address that, though in this case 
> it seems to work without too much difficulty:

ha ha, except that example was running in 0.8 :).    Prior to 0.8 you need to 
use an undocumented attribute _local_remote_pairs.   Undocumented because, it 
was never the best way to do this and in 0.8 it isn't needed anymore.  But for 
now:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base= declarative_base()

class A(Base):
    __tablename__ = "a"

    id1 = Column(String, primary_key=True)
    id2 = Column(String, primary_key=True)

class B(Base):
    __tablename__ = "b"
    id = Column(Integer, primary_key=True)
    a_id = Column(String)

A.bs = relationship("B", 
            primaryjoin="B.a_id == A.id1 + A.id2",
            foreign_keys="B.a_id",
            _local_remote_pairs=[(A.__table__.c.id1, B.__table__.c.a_id), 
                            (A.__table__.c.id2, B.__table__.c.a_id)],
            viewonly=True)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)

s.add_all([
    A(id1="x", id2="y", bs=[
        B(a_id="xy"),
        B(a_id="xy")
    ]),
    A(id1="q", id2="p", bs=[
        B(a_id="qp")
    ])
])

s.commit()

print s.query(A).first().bs

for a in s.query(A).options(joinedload(A.bs)):
    print a.bs

-- 
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