Inheriting a functionality in SQLA

15 views
Skip to first unread message

AlexVhr

unread,
Nov 20, 2012, 4:31:33 AM11/20/12
to sqlal...@googlegroups.com

I'm trying to incapsulate some functionality (some columns mainly) into base classes to inherit my models from them. The setup looks like this:

class EntityTemplate():
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer(), primary_key=True)
    timestamp = Column(DateTime())

class DocumentTemplate(EntityTemplate):
    date = Column(Date())
    number = Column(String(5))

Entity = declarative_base(cls=EntityTemplate, name='Entity')
Document = declarative_base(cls=DocumentTemplate, name='Document')

I'm trying to use it like this:

class Customer(Entity):    
    name = Column(String(25))
    address = Column(String(50))

class Invoice(Document):
    customer_id = Column(Integer, ForeignKey('customer.id'))
    customer = relationship("Customer")
    total = Column(Numeric(10,2))

Entity.metadata.create_all(engine)
Document.metadata.create_all(engine)

But on the last line I get this:

    sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column
'invoice.customer_id' could not find table 'customer' with which to generate
 a foreign key to target column 'id'

If I inherit Invoice from Entity instead of Document, everything is fine (except the fact that columns date and number are missing). Why? (I'm using SQLAlchemy-0.7.9-py3.2). Thanks!

Robert Forkel

unread,
Nov 20, 2012, 10:08:54 AM11/20/12
to sqlal...@googlegroups.com

As far as i know each declarative Base has its own metadata registry. You are using two. Why not use multiple mixins to inherit the columns?

--
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/-/2IsSRLhqqqAJ.
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.

Michael Bayer

unread,
Nov 20, 2012, 8:57:34 PM11/20/12
to sqlal...@googlegroups.com
the use of two different declarative_base() makes this more complicated as there is no common MetaData collection between the two classes which allows foreign keys to be resolve based on string names, as well as class names like "Customer" to be resolved.  the Base + MetaData combination represent a pair of registries that allow these string lookups to work.

So using one declarative base would solve the issue, else you need to forego the usage of string identifiers and pass object references instead:

customer_id = Column(Integer, ForeignKey(Customer.id))
customer = relationship(Customer)

but there's really no need to use two different declarative bases, your EntityTemplate and DocumentTemplate are mixins, which if you'd like them to be packed into a single base class can be accomplished using a subclass of a single Base with the __abstract__ = True flag.



Alexey Vihorev

unread,
Nov 21, 2012, 7:44:48 AM11/21/12
to sqlal...@googlegroups.com

Yes, I tried mix-in approach, and it works, thanks.

Alexey Vihorev

unread,
Nov 21, 2012, 8:44:44 PM11/21/12
to sqlal...@googlegroups.com

Thanks for the clarification, it works now.

 

From: sqlal...@googlegroups.com [mailto:sqlal...@googlegroups.com] On Behalf Of Michael Bayer
Sent: 21 ноября 2012 г. 3:58
To: sqlal...@googlegroups.com
Subject: Re: [sqlalchemy] Inheriting a functionality in SQLA

 

 

On Nov 20, 2012, at 4:31 AM, AlexVhr wrote:

--

Reply all
Reply to author
Forward
0 new messages