Inherited abstract model with relationship causing "Cannot compile Column object until its 'name' is assigned."

1,046 views
Skip to first unread message

TomS.

unread,
Aug 30, 2016, 1:54:38 PM8/30/16
to sqlal...@googlegroups.com
Hi,

I would like to create an abstract model which should be inherited.
Unfortunately, I am not allowed to used Foreign Keys, this is the reason
why I introduced work around via relationship. Here is the whole code:

class DepTest(db.Model):

__tablename__ = u'deptest'
__bind_key__ = u'section'

department_pk_id = db.Column(db.Integer, primary_key=True)
department_id = db.Column(db.Integer)
department_name = db.Column(db.String(1000))


class PPLTest(db.Model):

__abstract__ = True

person_pk_id = db.Column(db.Integer, primary_key=True)
person_name = db.Column(db.String(1000))
person_surname = db.Column(db.String(1000))
department_id = db.Column(db.Integer)

@hybrid_property
def person_name_surname(self):
return self.person_name + u' ' + self.person_surname


class Level1(PPLTest):

__tablename__ = u'ppl_level1'
__bind_key__ = u'section'

department = relationship(
DepTest,
primaryjoin=remote(DepTest.department_id) == foreign(
PPLTest.department_id))


But I get "Cannot compile Column object until its 'name' is assigned."

So I defined department (in Level1) using @declared_attr:

def department(clss):
return relationship(DepTest,
primaryjoin=lambda:
remote(DepTest.department_id) == foreign(
clss.department_id)
)

and now it works as expected. The question is - is it defined properly,
or I should be aware of sth?

Thank you for any suggestions!

Cheers

Mike Bayer

unread,
Aug 30, 2016, 2:25:35 PM8/30/16
to sqlal...@googlegroups.com
Yes, using a lambda here, or alternatively using a string-eval, is a
good way to defer evaluation of that primaryjoin until declarative has
set things up and put names in your Column objects.

Just curious to see the stack trace here because I don't see where the
Column needs to actually be compiled into a string.

TomS.

unread,
Sep 2, 2016, 10:25:35 AM9/2/16
to sqlal...@googlegroups.com
Thank you!

Flask==0.10.1
Flask-SQLAlchemy==2.0
SQLAlchemy==1.0.14

Here it is:

Traceback (most recent call last):
File "testing.py", line 20, in <module>
q = testm.Level1.query.all()
File
"/test/_env/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py",
line 452, in __get__
mapper = orm.class_mapper(type)
File "/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/base.py",
line 421, in class_mapper
mapper = _inspect_mapped_class(class_, configure=configure)
File "/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/base.py",
line 400, in _inspect_mapped_class
mapper._configure_all()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line
1167, in _configure_all
configure_mappers()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line
2770, in configure_mappers
mapper._post_configure_properties()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line
1710, in _post_configure_properties
prop.init()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py",
line 183, in init
self.do_init()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py",
line 1629, in do_init
self._setup_join_conditions()
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py",
line 1704, in _setup_join_conditions
can_be_synced_fn=self._columns_are_mapped
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py",
line 1977, in __init__
self._check_foreign_cols(self.primaryjoin, True)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py",
line 2481, in _check_foreign_cols
self.prop
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/elements.py",
line 506, in __str__
return unicode(self.compile()).encode('ascii', 'backslashreplace')
File "<string>", line 1, in <lambda>
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/elements.py",
line 494, in compile
return self._compiler(dialect, bind=bind, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/elements.py",
line 500, in _compiler
return dialect.statement_compiler(dialect, self, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 395, in __init__
Compiled.__init__(self, dialect, statement, **kwargs)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 190, in __init__
self.string = self.process(self.statement, **compile_kwargs)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 213, in process
return obj._compiler_dispatch(self, **kwargs)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py",
line 93, in _compiler_dispatch
return meth(self, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 927, in visit_binary
return self._generate_generic_binary(binary, opstring, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 944, in _generate_generic_binary
binary.right._compiler_dispatch(self, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/annotation.py",
line 73, in _compiler_dispatch
self, visitor, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py",
line 81, in _compiler_dispatch
return meth(self, **kw)
File
"/test/_env/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py",
line 627, in visit_column
raise exc.CompileError("Cannot compile Column object until "
sqlalchemy.exc.CompileError: Cannot compile Column object until its
'name' is assigned.

>
>
>
>
>>

Mike Bayer

unread,
Sep 2, 2016, 10:38:34 AM9/2/16
to sqlal...@googlegroups.com
OH. ha, weird. OK, that was it trying to raise a different error,
"Could not locate any simple equality expressions "\
"involving locally mapped foreign key columns for "\
"%s join condition "\
"'%s' on relationship %s."

But that failed because it couldn't turn the join condition into a string.

But w/ lambda you don't get that error either huh ?

TomS.

unread,
Sep 2, 2016, 10:57:31 AM9/2/16
to sqlal...@googlegroups.com
It happens when Level1 is defined this way:

department = relationship(
DepTest,
primaryjoin=remote(DepTest.department_id) == foreign(
PPLTest.department_id))

# @declared_attr
# def department(clss):
# return relationship(DepTest,
# primaryjoin=lambda:
remote(DepTest.department_id) == foreign(
# clss.department_id)
# )

It is ok when defintion is as follows (with or without lambda):

# department = relationship(
# DepTest,
# primaryjoin=remote(DepTest.department_id) == foreign(
# PPLTest.department_id))

@declared_attr
def department(clss):
return relationship(DepTest,
primaryjoin=lambda:
remote(DepTest.department_id) == foreign(
clss.department_id)
)


>
>
>
>>

Mike Bayer

unread,
Sep 2, 2016, 11:49:42 AM9/2/16
to sqlal...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages