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.

Reply via email to