Evan James <thas...@gmail.com> wrote:
> Hi folks, > > I'm working on a SQLAlchemy-based app where we've decided to make some > infrastructure changes, in particular moving from reflection to declaration > for mapping the models. > > However, we're now running into issues where, after switching to declarative, > relationships aren't populated the way we expect when manipulated in Python. > For example, we have code that looks like this: > > class Widget(...): > def merge(self, other_widget): > """Merge the widgets, transferring the dependent items on the other > widget to this one.""" > for frobnicator in other_widget.frobnicators[:]: > frobnicator.widget = self > > meta.Session.delete(other_widget) > > > This code worked as hoped-for when we were reflecting on the database to > create our mappers, but after switching to declarative, the dependent items > are cascade-deleted on commit when other_widget is deleted, rather than being > preserved as children of the merged widget. > > It's not difficult to fix this particular issue - explicitly removing the > frobnicators from the other_widget.frobnicators collection will prevent them > from being deleted, and then the merged widget correctly has them - but we're > finding we have a class of bugs where relationships aren't being handled the > same way as before. Unfortunately, "build a comprehensive test suite" is one > of the infrastructure changes we're in the process of making - which means > it's not done yet and we can't easily track down all the places we could get > tripped up. We would really prefer to resolve this by changing the > definitions in the models, not by changing the application code that > manipulates the membership of relationships. Essentially the issue is likely because the mappings in these two examples are not equivalent; the reflection based version has Widget.frobnicator and Frobnicator.widget communicating with each other through a backref, and the declarative version does not. Assuming you’re on SQLA 0.9, the reflective version is taking advantage of the behavior introduced in http://docs.sqlalchemy.org/en/rel_0_9/changelog/migration_09.html#backref-handlers-can-now-propagate-more-than-one-level-deep; that is, adding frobnicator to first_widget.frobincators affects the backref of frobnicator.widget which then automatically performs the remove of second_widget.frobnicators. The declarative version does not make any use of the “backref” or “back_populates” keyword so cannot take advantage of this behavior; it doesn’t track any linkage between these two sides. The section http://docs.sqlalchemy.org/en/rel_0_9/orm/backref.html?highlight=backref talks about how to configure either backref or back_populates between mutually-dependent relationships. > I've created a reduced test case here which specifically displays the > behavior we're having trouble with in minimal form. If one line in the test > case is commented out, the test will pass for reflective models and fail for > declarative models; if the line is put back in, success and failure reverse. > > My question: How can we make relationships function identically in > declarative syntax as they did in reflective syntax? We thought we had > migrated mapping styles in a way that wouldn't change anything, but here we > are. What are we missing? > > Thanks, > Evan James > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.