Reputation: 2467
I use SQLAlchemy 0.5 and Python 2.6.6.
I want to select or create a referred object within an association_proxy's creator. My problem is, that I need a session for this, but I don't know where to get this in the creator callback.
How can I use the session an object belongs to in one of its association proxy's creator?
What I've tried, which does not work
I've found session.object_session
, but don't have any object in the callback, unless it is part of my ORM object. If it is part of my object, the caller won't be called as a method (the first argument is the value of the proxy, not the object's reference):
class Event(ManagerBase):
# If association_proxy calls this, 'self' is the key, not the
# reference to the calling instance.
def _field_find_or_create(self, key, val):
session = session.object_session(self)
field = session.query(Field).filter_by(name=key).first()
if not field:
field = Field(name=key)
return EventFieldValue(field=field, value=val)
fields = association_proxy("field_values", "value",
creator=_field_find_or_create)
Can I pass the object itself to the creators function? In this case I could call object_session on this object.
My project uses several sessions, because of this I have to determine the concrete session on execution of the creator.
Upvotes: 3
Views: 589
Reputation: 170
I think what you need is a validate method:
from sqlalchemy.orm import validates, object_session
class Event(ManagerBase):
value = relationship(FieldValue)
fields = association_proxy("field_values", "value",
creator=lambda group: FieldValue(value=value))
@validates("field_values")
def _validate_field_values(self, key, value):
session = object_session(self)
if session is not None:
v = value.value
with session.no_autoflush:
uvalue = session.query(FieldValue) \
.filter_by(name=a) \
.first()
if uvalue:
session.expunge(value)
return ugroup
return value
The credits goes to https://groups.google.com/forum/#!topic/sqlalchemy/RMDI1SnGhd0.
Upvotes: 1
Reputation: 21582
This problem persists in SQLAlchemy 0.7 as well. I've had the same problem in a slightly different context. Because the associationproxy is a Python descriptor and descriptors operate on the class level you can't give the creator function a reference to a bound method (which operate on the instance level).
I arrived at the following solution:
My code looks like this:
def find_object(name):
# Because we can't get a grip on the actual session we instead use a global
# session for querying this instance.
session = Session()
obj = Model.query(session).filter_by(name=name).first()
# We also have to dump the reference to that session, so the created object
# can be used on other sessions.
session.expunge(obj)
# We don't need that session any more.
session.close()
return obj
Upvotes: 0