KeyError when adding objects to SQLAlchemy association object
Like van said, the problem stay in the __init__
method of the Association Object.
In fact, if Tablet or Correspondent classes don't define an __init__
method or don't pass any parameter, the solution doesn't work (no argument expected).
I found an alternative solution. It's easy to detect which class has to be proxied, so it can be assigned to the right field (and still work on adding more associations):
class Tablet_Correspondent(db.Model):
# ...
def __init__(self, proxied=None):
if type(proxied) is Tablet:
self.tablet = proxied
elif type(proxied) is Correspondent:
self.correspondent = proxied
The problem with your code is in the .__init__
method. If you are to debug-watch/print()
the parameters, you will notice that the parameter tablet
is actually an instance of Correspondent
:
class Tablet_Correspondent(db.Model):
def __init__(self, tablet=None, correspondent=None):
print "in __init__: ", tablet, correspondent
self.tablet = tablet
self.correspondent = correspondent
The reason for this is the way SA creates new values. From documentation Creation of New Values:
When a list
append()
event (or setadd()
, dictionary__setitem__()
, or scalar assignment event) is intercepted by the association proxy, it instantiates a new instance of the “intermediary” object using its constructor, passing as a single argument the given value.
In your case when you call tab.correspondents.append(cor)
, the Tablet_Correspondent.__init__
is called with single argument cor
.
Solution? If you will only be adding Correspondents
to the Tablet
, then just switch the parameters in the __init__
. In fact, remove the second parameter completely.
If, however, you will also be using cor.tablets.append(tab)
, then you need to explicitely use the creator
argument to the association_proxy
as explained in the documentation linked to above:
class Tablet(db.Model, GlyphMixin):
# ...
correspondents = association_proxy('tablet_correspondents', 'correspondent', creator=lambda cor: Tablet_Correspondent(correspondent=cor))
class Correspondent(db.Model, GlyphMixin):
# ...
tablets = association_proxy('correspondent_tablets', 'tablet', creator=lambda tab: Tablet_Correspondent(tablet=tab))