Hi folks,I have a structure where a poll is associated with one vote per user, and each vote is associated with several results.To manipulate this as easily as possible I use attribute_mapped_collection and association_proxy - please see the attached file or here : http://pastebin.com/CR2PCbCZIt works great but I have a question. The POLL_VOTES table, i.e. my association table between the polls & the results, has a special field called VOTE_DT. It's correctly populated at insert time but I'd like it to be automatically updated whenever the underlying collection (the results) is updated.Is it possible ? I documented the expected behaviour in the code snippet (bottom of the code).
> Hi Mike,
>
> Thanks for your prompt answer !
>
> Thanks for fixing my "default" field - makes complete sense.
> Besides I added the "vote_dt" assignment in the PollVote constructor but it seems that this constructor is called only once, i.e. after the first "result_values_by_user" assignment : poll.result_values_by_user[joe] = set(["A", "B", "C"])
>
> It seems that the 2 further "result_values_by_user" assignments don't trigger the constructor - please see the SQL trace below. What I'm trying to achieve is to automatically update this date not only at row creation time, but also when the underlying collection is modified.
>
> Am I missing something here ?
OK so look at the terminiology - "update this date" - you're looking for an UPDATE to the row, so an __init__ does not correspond to that. Sometimes we do on-updates at the SQL level using "onupdate", but that's to respond to something else being updated. In this case, you want the date on POLL_VOTES updated whenever its related POLL_RESULTS entries change as well (right ?) - so to get every kind of change on an attribute we can use attribute events:
from sqlalchemy import event
@event.listens_for(PollVote.results, "append")
@event.listens_for(PollVote.results, "remove")
@event.listens_for(PollVote.results, "set")
def _on_vote(target, value, initiator):
target.vote_dt = datetime.datetime.now()
I think I'm going to beef up the @validates decorator, which is a convenience decorator for the above, to include the ability to intercept deletes.