On Sep 7, 2011, at 4:40 AM, werner wrote:

> or:
> Region_LV.language = sao.relationship('Language',
>                   primaryjoin="Country_LV.fk_language_id==Language.id",
>                   foreign_keys=[Country_LV.__table__.c.fk_language_id])
> 
> I get:
> sqlalchemy.exc.ArgumentError: Column-based expression object expected for 
> argument 'foreign_keys'; got: 'Country_LV.fk_language_id', type <type 'str'>

this one above is the one that doesn't make any sense (also its probably how 
the relationship should be set up).   Clearly x.__table__.c.somename is a 
Column object, not a string.   Something is up with what you're sending it.     
I've tried to reproduce with no luck.  See attached.   Also I don't even need 
the primaryjoin/foreignkeys if the originating Table upon which the view is 
based has foreign keys to the parent.


from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import DDLElement
from sqlalchemy.sql import table
from sqlalchemy.ext import compiler

Base= declarative_base()

# first the view stuff as it is on the wiki
class CreateView(DDLElement):
    def __init__(self, name, selectable):
        self.name = name
        self.selectable = selectable

class DropView(DDLElement):
    def __init__(self, name):
        self.name = name

@compiler.compiles(CreateView)
def compile(element, compiler, **kw):
    return "CREATE VIEW %s AS %s" % (element.name, compiler.sql_compiler.process(element.selectable)) 

@compiler.compiles(DropView)
def compile(element, compiler, **kw):
    return "DROP VIEW %s" % (element.name)

def view(name, metadata, selectable):
    t = table(name)

    for c in selectable.c:
        c._make_proxy(t)

    CreateView(name, selectable).execute_at('after-create', metadata)
    DropView(name).execute_at('before-drop', metadata)
    return t


# now do an example using declartive

Base = declarative_base()

class MoreStuff(Base):
    __tablename__ = 'morestuff'
    id = Column(Integer, primary_key=True)

    # if you use this one, then we don't even need the primaryjoin/foriegn_keys
    # on the view, the FK propagates out
    # stuff_id = Column(Integer, ForeignKey('stuff.id'))

    # ... but lets say it wasn't there
    stuff_id = Column(Integer)
    data = Column(String(50))

class MSView(Base):
    __table__ = view("msview", Base.metadata,
        MoreStuff.__table__.select()
    )
    __mapper_args__ = {"primary_key":__table__.c.id}

# cannot reproduce your error.

class Stuff(Base):
    __tablename__ = 'stuff'
    id = Column(Integer, primary_key=True)
    data = Column(String(50))

    # works
    #msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys="[MSView.stuff_id]")

    # works
    #msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys="MSView.stuff_id")

    # doesn't work, tries to resolve __table__ as a column
    #msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys="[MSView.__table__.c.stuff_id]")

    # doesn't work, tries to resolve __table__ as a column
    #msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys="MSView.__table__.c.stuff_id")

    # works
    #msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys=[MSView.stuff_id])

    # works
    msview = relationship("MSView", primaryjoin="Stuff.id==MSView.stuff_id", foreign_keys=[MSView.__table__.c.stuff_id])


# all is well

e = create_engine('sqlite://', echo=True)


Base.metadata.create_all(e)

e.execute(Stuff.__table__.insert(),
        {'data':'apples'},
        {'data':'pears'},
        {'data':'oranges'},
        {'data':'orange julius'},
        {'data':'apple jacks'},
    )

e.execute(MoreStuff.__table__.insert(),
        {'stuff_id':3, 'data':'foobar'},
        {'stuff_id':4, 'data':'foobar'}
    )

s = Session(e)

print s.query(Stuff).options(eagerload("msview")).all()
-- 
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