im not sure of the cause of that error, can you attach a full test case which illustrates this message being generated ?
>
> I noticed that the method __mapper_args__(cls) is always called before
> id(cls) (which is never called, probably due to the error.
the __mapper_args__(cls) method here directly calls upon .id, so if you see .id() not being called it suggests some other form of .id is being used.
Is it possible that Base or something else has a conflicting "id" attribute?
>
> Also, is there a way to add the discriminator column to the mixin (if
> i just directly add it to the declaration, this gave another maybe
> related error)?
maybe, let's start with the general idea of the mixin you're going to send me as a working script.
> this is the testcase:
>
>
> What am i missing?
the issue here is one of Python inheritance mechanics. Declarative calls upon @declared_attr in terms of the class, that is, we look through the class to find each @declared_attr, but when we find one, we invoke it by just calling it as a method, that is, getattr(cls, name). This works for things like __mapper_args__ which remain as callable methods on classes like Person, Engineer. But "id", when that is declared on Person is immediately replaced with a mapping. By the time you get to Engineer, the id() method is gone.
So for inheriting cases you need to build a mixin that is applied to every subclass. This makes sense because a mixin with a column on it implies that the column is being associated only with that immediate class - if you wanted a subclass to act as single table inheritance, you'd omit this class. In this case you want the same column on all subclasses. So you can do it like this (note also using declarative.has_inherited_table helper):
class InheritMixin(object):
@declared_attr
def __tablename__(cls):
return cls.__name__
@declared_attr
def id(cls):
return Column(Integer, primary_key = True)
@declared_attr
def __mapper_args__(cls):
if not has_inherited_table(cls):
return {'polymorphic_on': 'discriminator'}
else:
return {'polymorphic_identity': cls.__name__}
class Inherits(InheritMixin):
@declared_attr
def id(cls):
super_id = super(Inherits, cls).id
return Column(Integer, ForeignKey(super_id),primary_key = True)
class Person(InheritMixin, Base):
discriminator = Column(String(50))
name = Column(String(50))
class Engineer(Inherits, Person):
job = Column(String(50))
this should be in the docs so I've added ticket #2471 to handle this.
> --
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To post to this group, send email to sqlal...@googlegroups.com.
> To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>
> To unsubscribe from this group, send email to sqlalchemy+unsubscribe@googlegroups.com.
> To unsubscribe from this group, send email to sqlalchemy+unsubscribe@googlegroups.com.
yeah I suppose if you're building out joined inheritance more than one level then this becomes awkward. I never use joined inh more than one level because it has too much of an impact on queries.
the metaclass as you mention is always the last resort when the various declarative trickery reaches its limit. I'm not thrilled about the metaclass approach because it quickly gets confusing and shouldn't be necessary. though in this case without some extra mechanism on declarative, such as a __pre_declare__() method of some kind, it might be the only approach.
--
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/MH4tZazKT0EJ.
To post to this group, send email to sqlal...@googlegroups.com.
To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, 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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.