I don't see a different solution in here. It is all just an extension of the "you must share something" idea. I could've explicitly pointed out all the possible ways to inject a common metadata into the declarative base, etc but in the end you still have a common metadata that you import/inject.
Viktor mentioned already that he understands the common Base option so I was assuming it was clear that effectively Base==(metadata+mapper). It isn't clear what his goal actually *is* here. Is it to describe relationships between data in MyBase to data in YourBase? Is it to get all of the mappers working with the same DBSession? If there is nothing shared between the different package's tables, then the sanest approach is to just use them separately and not attempt to merge things together. If you do want to share things, the sanest approach I know is to use a common Base. On Fri, Dec 16, 2011 at 9:26 AM, Michael Bayer <[email protected]>wrote: > > On Dec 16, 2011, at 3:23 AM, Michael Merickel wrote: > > > In SQLAlchemy the "metadata" is the central object that binds tables > together and describes their relationships. It is not possible to describe > relationships between tables that are defined using different metadata > objects. > > you can but it's tedious - either ForeignKey(myothertable.c.id) or use > primaryjoin + foreign_keys inside of each relationship(). > > > > As you know already, each Base creates its own shared metadata object > between all of its subclasses. If you really do want to share tables > between addons you either need to define that table per-metadata-object, or > share those particular objects via a common package. > > You can share a single MetaData object with multiple Base objects by > passing it in as an argument to declarative_base(). However, and this is > something that should be improved, MetaData is only the registry of > name->Table objects, not the *other* registry of name->Class objects (and > at this point Chris is scratching his head like "What??? Why???"...its part > of the Core/ORM separation plus a lot of history). > > Both registries are used in different contexts, name->Table for the > ForeignKey object basically (and in some cases parts of relationship()), > and name->Class for the arguments passed orm.relationship() function. > > You can make two Base objects totally on top of the same registries like: > > Base1 = declarative_base() > Base2 = declarative_base(metadata=Base1.metadata) > Base2._decl_class_registry = Base1._decl_class_registry > > but what does this imply ? That you wouldn't have any same-named classes > on top of Base1 and Base2. That's why you might not want to do that. > There's a ticket to extend declarative to support full packagenames in the > "class" registry like relationship("mypackage.MyClass"), though that's not > how everyone might want to operate. Similarly, MetaData has to do with > tables, a multi-DB app may have any particular pattern of repeated table > names across multiple DBs so the ability to control those registries is > still important. > > There's two other ways to make yourself a Base that extends from a > "common" Base. The most common is to send cls: > > Base2 = declarative_base(cls=MyAppsUberBase) > > There's also now an __abstract__ flag that does this: > > class MyLocalBase(Base): > __abstract__ = True > > # custom things on my local apps' base > > That pattern hasn't been tested as much but should in theory be very > useful. > > > > > > If you'd like to also share the mapper relationships then you'll need to > share the Base subclasses (User, Product, etc). > > If this means, the classes must be on the same Base to use relationship() > between them, that's not true. The docs are pretty clear that > relationship() has no dependency on declarative, and that any declarative > class is just a syntactic trick for mapper(MyClass, mytable). You can > pass any mapped class or mapper() to relationship(). It's just the "look > it up from the string" part that uses the local registry. To help with > resolving import time issues, you can also send a callable like this: > > relationship(lambda: MyOtherClass) > > > > > > -- > You received this message because you are subscribed to the Google Groups > "pylons-discuss" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/pylons-discuss?hl=en. > > -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
