On 27.8.2015 22:13, Douglas Russell wrote: > Ok, thanks, that makes sense. > > Generally everything I see about SQLAlchemy referencing is using backref and > it > is convenient, but knowing that you actually think back_populates would be > your > preferred way to implement things is quite nice. I quite prefer that as I > think > it makes my code much more readable to have the relationship properties > declared > where they will exist.
+100 I came to the same conclusion a long time ago and have never looked back :-) Just my 2c, Ladislav Lenart > Cheers, > > Douglas > > On Monday, 24 August 2015 21:54:17 UTC-4, Michael Bayer wrote: > > > > On 8/24/15 9:21 PM, Mike Bayer wrote: >> >> >> On 8/24/15 7:41 PM, Douglas Russell wrote: >>> >>> | >>> def print_stuff(mapper, class_): >>> print getattr(class_, 'books') >>> >>> event.listen(mapper, 'mapper_configured', print_stuff) >>> >>> author = Author(name='Chuck Paluhniuk') >>> | >>> >>> When I run this code, the result is that when Author is first used, the >>> 'mapper_configured' event will fire and my print_stuff function callback >>> will run. >>> >>> The results is this: >>> >>> | >>> Traceback (most recent call last): >>> File "marshmallow_experiment.py", line 37, in <module> >>> author = Author(name='Chuck Paluhniuk') >>> File "<string>", line 2, in __init__ >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", >>> line 347, in _new_state_if_none >>> state = self._state_constructor(instance, self) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", >>> line 747, in __get__ >>> obj.__dict__[self.__name__] = result = self.fget(obj) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", >>> line 177, in _state_constructor >>> self.dispatch.first_init(self, self.class_) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py", >>> line 258, in __call__ >>> fn(*args, **kw) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", >>> line 2792, in _event_on_first_init >>> configure_mappers() >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", >>> line 2691, in configure_mappers >>> mapper, mapper.class_) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py", >>> line 218, in __call__ >>> fn(*args, **kw) >>> File >>> >>> "/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/events.py", >>> line 527, in wrap >>> fn(*arg, **kw) >>> File "marshmallow_experiment.py", line 33, in print_stuff >>> print getattr(class_, 'books') >>> AttributeError: type object 'Author' has no attribute 'books' >>> | >>> >>> Should not the backref be configured at that point? What I'm trying to >>> do >>> is use the mapper_configured event in order to autocreate >>> marshamallow-sqlalchemy schemas, which works fine except that because >>> books doesn't exist at the point when the callback function runs, the >>> resulting schema is also missing the books part. >>> >>> If I do this instead: >>> >>> | >>> author = Author(name='Chuck Paluhniuk') >>> print_stuff(None, Author) >>> | >>> >>> Then the result is: >>> >>> | >>> Author.books >>> | >> so you can see what's happening here. Author.books is being set up, but >> not within the event. In this case Author is being configured before >> Book, and as far as it knows, that's it, it's done. The event is >> called. >> Book hasn't been touched so therefore neither has "books". Only outside >> of the whole thing, where Book also got set up, does your inspection >> work. >> >> The solution is to either use back_populates instead of backref, which is >> probably the only way the ORM would have done it today if starting again, >> or use the "after_configured()" event >> >> <http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.MapperEvents.after_configured>http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.MapperEvents.after_configured >> >> <http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.MapperEvents.after_configured> >> which is intentionally here so that you can do things that require all >> known mappers to be fully set up, which is the case here. >> >> As is so often the case I'm horrified the API docs don't have cross >> linking here. doing that.. > I've pushed up new descriptions and full cross-linking between > configure_mappers(), mapper_configured(), before_configured() and > after_configured(), for 0.9, 1.0, 1.1, master. Should be up on the site > in > a little while. > > -- > 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 > <mailto:sqlalchemy+unsubscr...@googlegroups.com>. > To post to this group, send email to sqlalchemy@googlegroups.com > <mailto: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.