Deferring a many-to-many mapping

13 views
Skip to first unread message

Brian the Lion

unread,
Sep 12, 2014, 8:46:45 PM9/12/14
to sqlal...@googlegroups.com
Hi all,

I am having trouble deferring a many-to-many mapping. I just had a couple of questions related there-to:

(1) The most visible implementations of vanilla many-to-many mappings seem to use sqlalchemy.Table(...). Is that, indeed, the accepted practice? One alternative would be to use a mapped class, but that seems less than parsimonious.

(2) There don't appear to be any particularly visible examples of deferred many-to-many mappings. The best I was able to come up with was along the lines of

class DeferredManyToMany(object):
     @declared_attr
     def __table__(cls):
          return Table(cls.__tablename__, cls.metadata, ....)

Is this also accepted practice?

(3) Upon execution, the __table__(...) method gets called twice and throws an InvalidRequestError saying the table is already defined. Giving extend_existing=True in the Table constructor fixes things. Can somebody provide some background on that?

(4) Now I'm trying to add a PrimaryKeyConstraint and things are going to crap again. See http://pastebin.com/1tQEWh71 . Is there some additional magic that I'm missing?

I'm on sqlalchemy 0.9.7.

Thanks!
~br

Michael Bayer

unread,
Sep 13, 2014, 11:03:52 AM9/13/14
to sqlal...@googlegroups.com

On Sep 12, 2014, at 8:46 PM, Brian the Lion <brian...@gmail.com> wrote:

> Hi all,
>
> I am having trouble deferring a many-to-many mapping. I just had a couple of questions related there-to:
>
> (1) The most visible implementations of vanilla many-to-many mappings seem to use sqlalchemy.Table(...). Is that, indeed, the accepted practice? One alternative would be to use a mapped class, but that seems less than parsimonious.

all parsimony aside, you can map to that table and call it the association pattern: http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#association-object , and you can combine the two approaches too, as long as you take care to make the appropriate relationships “viewonly” (see the green note at the end of that section).


>
> (2) There don't appear to be any particularly visible examples of deferred many-to-many mappings. The best I was able to come up with was along the lines of
>
> class DeferredManyToMany(object):
> @declared_attr
> def __table__(cls):
> return Table(cls.__tablename__, cls.metadata, ....)
>
> Is this also accepted practice?

what is the nature of the “deferment” here? Are you using reflection, or just wanting to organize your code in some way where classes are declared before tables (in which case …. straight up classical mappings http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html?highlight=classical#classical-mappings do that) ? The code example in your paste doesn’t make apparent why __table__() needs to be a function. It sort of looks a bit like you’re trying to emulate what a mixin is used for, e.g. a fixed series of columns: http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html?highlight=declarative%20mixin#mixin-and-custom-base-classes.



>
> (3) Upon execution, the __table__(...) method gets called twice and throws an InvalidRequestError saying the table is already defined. Giving extend_existing=True in the Table constructor fixes things. Can somebody provide some background on that?

as mentioned on IRC, add the “keep_existing” flag http://docs.sqlalchemy.org/en/rel_0_9/core/metadata.html?highlight=table#sqlalchemy.schema.Table.params.keep_existing which will allow the same table to be safely reused and ignore the given arguments (also I’ve made sure all those arguments are cross-referenced, so click around the “see also” boxes” to get a full picture).


>
> (4) Now I'm trying to add a PrimaryKeyConstraint and things are going to crap again. See http://pastebin.com/1tQEWh71 . Is there some additional magic that I'm missing?

keep_existing would work better here.

Brian Rossa

unread,
Sep 15, 2014, 3:42:15 PM9/15/14
to sqlal...@googlegroups.com
Mike,

Thanks for the feedback!
 
> (1) The most visible implementations of vanilla many-to-many mappings seem to use sqlalchemy.Table(...). Is that, indeed, the accepted practice? One alternative would be to use a mapped class, but that seems less than parsimonious.

all parsimony aside, you can map to that table and call it the association pattern: http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#association-object , and you can combine the two approaches too, as long as you take care to make the appropriate relationships "viewonly" (see the green note at the end of that section).

Noted.
 
> (2) There don't appear to be any particularly visible examples of deferred many-to-many mappings. The best I was able to come up with was along the lines of
>
> class DeferredManyToMany(object):
>      @declared_attr
>      def __table__(cls):
>           return Table(cls.__tablename__, cls.metadata, ....)
>
> Is this also accepted practice?

what is the nature of the "deferment" here?    Are you using reflection, or just wanting to organize your code in some way where classes are declared before tables
... 
It sort of looks a bit like you're trying to emulate what a mixin is used for, e.g. a fixed series of columns
 
Yes, apologies, I realize now that I've abused your term "deferred." Indeed, all I'm trying to do is emulate the mixin pattern of model design for sqlalchemy.Table()s. I just want to be able to declare the Table()s before mixing them with the Base. The Paste (http://pastebin.com/1tQEWh71) shows one possible approach for a trivially small model, but I am open to other approaches.
 
> (3) Upon execution, the __table__(...) method gets called twice and throws an InvalidRequestError saying the table is already defined. Giving extend_existing=True in the Table constructor fixes things. Can somebody provide some background on that?

as mentioned on IRC, add the "keep_existing" flag http://docs.sqlalchemy.org/en/rel_0_9/core/metadata.html?highlight=table#sqlalchemy.schema.Table.params.keep_existing which will allow the same table to be safely reused and ignore the given arguments (also I've made sure all those arguments are cross-referenced, so click around the "see also" boxes" to get a full picture).

I will try keep_existing and report back.

> (4) Now I'm trying to add a PrimaryKeyConstraint and things are going to crap again. See http://pastebin.com/1tQEWh71 . Is there some additional magic that I'm missing?

keep_existing would work better here.

Thanks! Kudos for the support and for all your hard work on the software.

Best,
~br

On Sat, Sep 13, 2014 at 11:01 AM, Michael Bayer <mik...@zzzcomputing.com> wrote:

On Sep 12, 2014, at 8:46 PM, Brian the Lion <brian...@gmail.com> wrote:

> Hi all,
>
> I am having trouble deferring a many-to-many mapping. I just had a couple of questions related there-to:
>
> (1) The most visible implementations of vanilla many-to-many mappings seem to use sqlalchemy.Table(...). Is that, indeed, the accepted practice? One alternative would be to use a mapped class, but that seems less than parsimonious.

all parsimony aside, you can map to that table and call it the association pattern: http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#association-object , and you can combine the two approaches too, as long as you take care to make the appropriate relationships "viewonly" (see the green note at the end of that section).


>
> (2) There don't appear to be any particularly visible examples of deferred many-to-many mappings. The best I was able to come up with was along the lines of
>
> class DeferredManyToMany(object):
>      @declared_attr
>      def __table__(cls):
>           return Table(cls.__tablename__, cls.metadata, ....)
>
> Is this also accepted practice?

what is the nature of the "deferment" here?    Are you using reflection, or just wanting to organize your code in some way where classes are declared before tables (in which case ....  straight up classical mappings http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html?highlight=classical#classical-mappings do that) ?  The code example in your paste doesn't make apparent why __table__() needs to be a function.   It sort of looks a bit like you're trying to emulate what a mixin is used for, e.g. a fixed series of columns: http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html?highlight=declarative%20mixin#mixin-and-custom-base-classes.




>
> (3) Upon execution, the __table__(...) method gets called twice and throws an InvalidRequestError saying the table is already defined. Giving extend_existing=True in the Table constructor fixes things. Can somebody provide some background on that?

as mentioned on IRC, add the "keep_existing" flag http://docs.sqlalchemy.org/en/rel_0_9/core/metadata.html?highlight=table#sqlalchemy.schema.Table.params.keep_existing which will allow the same table to be safely reused and ignore the given arguments (also I've made sure all those arguments are cross-referenced, so click around the "see also" boxes" to get a full picture).


>
> (4) Now I'm trying to add a PrimaryKeyConstraint and things are going to crap again. See http://pastebin.com/1tQEWh71 . Is there some additional magic that I'm missing?

keep_existing would work better here.

--
You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/VPleXpb5zLQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages