[sqlalchemy] Re: Abstract base class
Hi, I have a similar task, so I tried to use your proposal, but it didn't work for me: === from sqlalchemy import types as satypes from sqlalchemy import schema as saschema from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta from sqlalchemy.orm import scoped_session, sessionmaker class BaseType(DeclarativeMeta): def __init__(newcls, classname, bases, dict_): newcls.notes = saschema.Column(satypes.String) DeclarativeMeta.__init__(newcls, classname, bases, dict_) MetaData = saschema.MetaData(bind=create_engine('sqlite:///:memory:')) Session = scoped_session(sessionmaker(bind=MetaData.bind)) Base = declarative_base(metadata=MetaData, mapper=Session.mapper, metaclass=BaseType) class MasterEntity(Base): __tablename__ = master id = saschema.Column(satypes.Integer, primary_key=True) status = saschema.Column(satypes.CHAR(length=1), default=A) print [ _c.key for _c in MasterEntity.__table__.columns ] # ['id', 'status'] # = the 'notes' column is missing === snip So, what am I doing wrong? Thanks in advance, Frank Btw.: Hello group and many thanks to Michael for this great piece of software! On Dec 16, 6:58 pm, Michael Bayer mike...@zzzcomputing.com wrote: anabstractbaseclassisn't going to set up the same fields on all descendants since the mapper()/Table() setup occurs during the creation of the individualclassusing the non-inheritedclassdict, and unique instances of each of the Column, etc. elements are required as well. concrete inheritance, as referenced in that post, was not designed to be used as a configurational spacesaver and always requires a mapped selectable for the base, which you don't have here, so it's not appropriate for this use case. So for this you'd need a custom metaclass: classMyMeta(DeclarativeMeta): def __init__(cls, classname, bases, dict_): cls.notes = Column(String) DeclarativeMeta.__init__(cls, classname, bases, dict_) Base= declarative_base(metaclass=MyMeta) On Dec 16, 2008, at 12:36 PM, Joril wrote: Hi everyone! I need to declare a few unrelated classes (from a business perspective) that share some attributes/fields, so I thought I could use anabstractclassto group these common attributes (note that just a few classes should have them, not every one) This post http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it suggests to use mixins, but I can't get it to work, SQLA generates the tables without the common fields. I'm testing it with this script: from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy import create_engine # --- Tables definition Base= declarative_base() classAbstract(object): notes = Column(String) classConcrete(Base,Abstract): __tablename__ = 'concrete' id = Column(Integer, primary_key=True) # --- # DB creation engine = create_engine('sqlite:///:memory:', echo=True) Base.metadata.create_all(engine) Here's the sql call: CREATE TABLE concrete ( id INTEGER NOT NULL, PRIMARY KEY (id) ) What am I missing? Did I misunderstood how the mixin should be used? (I'm using SQLA 0.5rc4) Many thanks! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
oops, do it like this: class BaseType(DeclarativeMeta): def __init__(newcls, classname, bases, dict_): dict_['notes'] = saschema.Column(satypes.String) DeclarativeMeta.__init__(newcls, classname, bases, dict_) clearly we'll have to figure out a more user friendly pattern for this use case. On Dec 19, 2008, at 5:27 AM, FrankB wrote: Hi, I have a similar task, so I tried to use your proposal, but it didn't work for me: === from sqlalchemy import types as satypes from sqlalchemy import schema as saschema from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta from sqlalchemy.orm import scoped_session, sessionmaker class BaseType(DeclarativeMeta): def __init__(newcls, classname, bases, dict_): newcls.notes = saschema.Column(satypes.String) DeclarativeMeta.__init__(newcls, classname, bases, dict_) MetaData = saschema.MetaData(bind=create_engine('sqlite:///:memory:')) Session = scoped_session(sessionmaker(bind=MetaData.bind)) Base = declarative_base(metadata=MetaData, mapper=Session.mapper, metaclass=BaseType) class MasterEntity(Base): __tablename__ = master id = saschema.Column(satypes.Integer, primary_key=True) status = saschema.Column(satypes.CHAR(length=1), default=A) print [ _c.key for _c in MasterEntity.__table__.columns ] # ['id', 'status'] # = the 'notes' column is missing === snip So, what am I doing wrong? Thanks in advance, Frank Btw.: Hello group and many thanks to Michael for this great piece of software! On Dec 16, 6:58 pm, Michael Bayer mike...@zzzcomputing.com wrote: anabstractbaseclassisn't going to set up the same fields on all descendants since the mapper()/Table() setup occurs during the creation of the individualclassusing the non-inheritedclassdict, and unique instances of each of the Column, etc. elements are required as well. concrete inheritance, as referenced in that post, was not designed to be used as a configurational spacesaver and always requires a mapped selectable for the base, which you don't have here, so it's not appropriate for this use case. So for this you'd need a custom metaclass: classMyMeta(DeclarativeMeta): def __init__(cls, classname, bases, dict_): cls.notes = Column(String) DeclarativeMeta.__init__(cls, classname, bases, dict_) Base= declarative_base(metaclass=MyMeta) On Dec 16, 2008, at 12:36 PM, Joril wrote: Hi everyone! I need to declare a few unrelated classes (from a business perspective) that share some attributes/fields, so I thought I could use anabstractclassto group these common attributes (note that just a few classes should have them, not every one) This post http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it suggests to use mixins, but I can't get it to work, SQLA generates the tables without the common fields. I'm testing it with this script: from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy import create_engine # --- Tables definition Base= declarative_base() classAbstract(object): notes = Column(String) classConcrete(Base,Abstract): __tablename__ = 'concrete' id = Column(Integer, primary_key=True) # --- # DB creation engine = create_engine('sqlite:///:memory:', echo=True) Base.metadata.create_all(engine) Here's the sql call: CREATE TABLE concrete ( id INTEGER NOT NULL, PRIMARY KEY (id) ) What am I missing? Did I misunderstood how the mixin should be used? (I'm using SQLA 0.5rc4) Many thanks! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Friday 19 December 2008 16:58:12 Michael Bayer wrote: oops, do it like this: class BaseType(DeclarativeMeta): def __init__(newcls, classname, bases, dict_): dict_['notes'] = saschema.Column(satypes.String) DeclarativeMeta.__init__(newcls, classname, bases, dict_) clearly we'll have to figure out a more user friendly pattern for this use case. can't u use multiple inheritance, in the case, as mixin/s? i use it in dbcook this way, using the bases[1:] only as declaration-bringers. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
Michael Bayer wrote: meta = MetaData() Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass) Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass) Base2._decl_class_registry = Base1._decl_class_registry Great! So now I have a MetaClass2 that extends MetaClass1, and they share a set of fields.. Works perfectly :) Another question if I may.. What would be the recommended way to identify a mapped object now? I mean, I could use something like isinstance(obj, Base1) or isinstance(obj, Base2) but is there a more concise way? It looks like Base1 and Base2 extend object directly.. This is a use case we can make easier in a future release. That'd be appreciated, surely :) Many thanks for your time, as always! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
isinstance(obj, (Base1, Base2)), or you could make yet another Base class below Base1 and Base2 and specify it as cls to declarative_base(). On Dec 18, 2008, at 3:06 AM, Joril wrote: Michael Bayer wrote: meta = MetaData() Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass) Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass) Base2._decl_class_registry = Base1._decl_class_registry Great! So now I have a MetaClass2 that extends MetaClass1, and they share a set of fields.. Works perfectly :) Another question if I may.. What would be the recommended way to identify a mapped object now? I mean, I could use something like isinstance(obj, Base1) or isinstance(obj, Base2) but is there a more concise way? It looks like Base1 and Base2 extend object directly.. This is a use case we can make easier in a future release. That'd be appreciated, surely :) Many thanks for your time, as always! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
Michael Bayer wrote(): isinstance(obj, (Base1, Base2)), or you could make yet another Base class below Base1 and Base2 and specify it as cls to declarative_base(). I see.. Thanks again, you are very helpful! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 17, 2008, at 2:28 AM, Joril wrote: Michael Bayer ha scritto: concrete inheritance, as referenced in that post, was not designed to be used as a configurational spacesaver and always requires a mapped selectable for the base, which you don't have here, so it's not appropriate for this use case. So for this you'd need a custom metaclass: I see, thanks! Now my problem is that I already have a custom metaclass, defining a set of common attributes for ALL my classes.. So, to declare additional fields for just a few classes, would it be ok to subclass the custom metaclass again and re-call declarative_base ()? To clarify: All classes have a timestamp attribute, and a few of them has a notes attribute too. Thanks again! yes that is entirely OK. A second declarative_base may share the metadata of the first, Base = declarative_base(metadata=somemetadata). If you want to use strings for relation() classes across the two bases, the _decl_class_registry would need to be shared as well: meta = MetaData() Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass) Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass) Base2._decl_class_registry = Base1._decl_class_registry This is a use case we can make easier in a future release. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
an abstract base class isn't going to set up the same fields on all descendants since the mapper()/Table() setup occurs during the creation of the individual class using the non-inherited class dict, and unique instances of each of the Column, etc. elements are required as well. concrete inheritance, as referenced in that post, was not designed to be used as a configurational spacesaver and always requires a mapped selectable for the base, which you don't have here, so it's not appropriate for this use case. So for this you'd need a custom metaclass: class MyMeta(DeclarativeMeta): def __init__(cls, classname, bases, dict_): cls.notes = Column(String) DeclarativeMeta.__init__(cls, classname, bases, dict_) Base = declarative_base(metaclass=MyMeta) On Dec 16, 2008, at 12:36 PM, Joril wrote: Hi everyone! I need to declare a few unrelated classes (from a business perspective) that share some attributes/fields, so I thought I could use an abstract class to group these common attributes (note that just a few classes should have them, not every one) This post http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it suggests to use mixins, but I can't get it to work, SQLA generates the tables without the common fields. I'm testing it with this script: from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy import create_engine # --- Tables definition Base = declarative_base() class Abstract(object): notes = Column(String) class Concrete(Base, Abstract): __tablename__ = 'concrete' id = Column(Integer, primary_key=True) # --- # DB creation engine = create_engine('sqlite:///:memory:', echo=True) Base.metadata.create_all(engine) Here's the sql call: CREATE TABLE concrete ( id INTEGER NOT NULL, PRIMARY KEY (id) ) What am I missing? Did I misunderstood how the mixin should be used? (I'm using SQLA 0.5rc4) Many thanks! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 3, 7:39 pm, Michael Bayer [EMAIL PROTECTED] wrote: On Dec 3, 2008, at 1:26 PM, Guillaume wrote: Hello, is there a way with the ORM layer to have abstract base class like in django ? http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base- classes sure, just pass along cls=MyBaseClass along to declarative_base(). You can also make your own metaclass if you wanted, and pass it in as metaclass=MyMetaClass, or you can use the individual components within declarative_base explicitly if you wanted to roll it yourself. This is all in the docstrings for declarative. So: class A(object): pass Base = declarative_base(cls=A) class B(Base): __tablename__ = 'b' id = Column(Integer, primary_key=True) b = B() if isinstance(b, A): print 'Success !' completes successfully, great ! Another somehow related question is there any plan for declarative base to support inheritance ala django ? declarative supports all three of SQLA's table inheritance forms fully.It pretty much happens automatically when you make a subclass, and you just need to pass along polymorphic_on/ polymorphic_identity into __mapper_args__. If Django supported some kind of inheritance scenario that we don't I'd be very interested to see that :) . The problem is not directly in the inheritance scenario, but rather creating an association to an abstract class. Let's say I have the following classes: CorporateCustomer and PrivateCustomer inheriting from the abstract class Customer. On the database side, I have the two following table: corporate_customer(id, customer_info, corporate_info) and private_customer(id, customer_info, private_info) (ids are generated by a unique sequence for all the database). Now I have also Order objects associated to Customer objects; the table looks like order(id, customer_id, order_info). Can I map this scenario directly in SQLA without creating some dummy view customer in the database ? (Just checked how I did it with Django: with a set of ugly wrapper method and views.) Regards, Guillaume --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 4, 2008, at 7:44 AM, Guillaume wrote: The problem is not directly in the inheritance scenario, but rather creating an association to an abstract class. Let's say I have the following classes: CorporateCustomer and PrivateCustomer inheriting from the abstract class Customer. On the database side, I have the two following table: corporate_customer(id, customer_info, corporate_info) and private_customer(id, customer_info, private_info) (ids are generated by a unique sequence for all the database). Now I have also Order objects associated to Customer objects; the table looks like order(id, customer_id, order_info). Can I map this scenario directly in SQLA without creating some dummy view customer in the database ? sure this is called concrete table inheritance. Though when you make a relation to Order, you need to declare these separately for CorporateCustomer and PrivateCustomer since the connection from a relational perspective is different. When concrete inheritance uses an abc, it maps to a union of the subtables so that you can load polymorphically. To do that with declarative you'd also have to create the Table objects separately and pull them in to each class using __table__. So with those limitations, if it were me I wouldn't use the concrete inheritance feature unless i needed to load Customer objects generically, I'd instead use Customer as a mixin class stated after the declarative base class. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
sure this is called concrete table inheritance. Though when you make a relation to Order, you need to declare these separately for CorporateCustomer and PrivateCustomer since the connection from a relational perspective is different. When concrete inheritance uses an abc, it maps to a union of the subtables so that you can load polymorphically. To do that with declarative you'd also have to create the Table objects separately and pull them in to each class using __table__. So with those limitations, if it were me I wouldn't use the concrete inheritance feature unless i needed to load Customer objects generically, I'd instead use Customer as a mixin class stated after the declarative base class. Which prety much means no generic query for Customer objects ... I'll go down the concrete inheritance path and create a couple of views for handling my abstract classes. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 4, 2008, at 11:18 AM, Guillaume wrote: sure this is called concrete table inheritance. Though when you make a relation to Order, you need to declare these separately for CorporateCustomer and PrivateCustomer since the connection from a relational perspective is different. When concrete inheritance uses an abc, it maps to a union of the subtables so that you can load polymorphically. To do that with declarative you'd also have to create the Table objects separately and pull them in to each class using __table__. So with those limitations, if it were me I wouldn't use the concrete inheritance feature unless i needed to load Customer objects generically, I'd instead use Customer as a mixin class stated after the declarative base class. Which prety much means no generic query for Customer objects ... I'll go down the concrete inheritance path and create a couple of views for handling my abstract classes. getting different concrete tables to connect to a common related table, with the configuration on the base class is definitely possible and its even clear where the code to do this would occur (right at the TODO in _adapt_inherited_property)...its just some complexity that I have balked on for now. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 3, 2008, at 1:26 PM, Guillaume wrote: Hello, is there a way with the ORM layer to have abstract base class like in django ? http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base- classes sure, just pass along cls=MyBaseClass along to declarative_base(). You can also make your own metaclass if you wanted, and pass it in as metaclass=MyMetaClass, or you can use the individual components within declarative_base explicitly if you wanted to roll it yourself. This is all in the docstrings for declarative. Another somehow related question is there any plan for declarative base to support inheritance ala django ? declarative supports all three of SQLA's table inheritance forms fully.It pretty much happens automatically when you make a subclass, and you just need to pass along polymorphic_on/ polymorphic_identity into __mapper_args__. If Django supported some kind of inheritance scenario that we don't I'd be very interested to see that :) . --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---