Declarative and common fields

49 views
Skip to first unread message

Joril

unread,
Sep 29, 2008, 11:01:00 AM9/29/08
to sqlalchemy
Hi everyone!
I'm new to SQLAlchemy and I'm using version 0.5rc1..
I need every entity class to have a few common fields, so I tried
writing an "abstract" base class, declarative-style, that every other
entity class would subclass. So for example:

---
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, DateTime, Integer

ORMBase = declarative_base()

class BaseObject(ORMBase):
id = Column(Integer, primary_key=True)
creation_time = Column(DateTime)
modify_time = Column(DateTime)

class TestEntity(BaseObject):
value = Column(String)
---

But SQLAlchemy complains that
sqlalchemy.exc.ArgumentError: Mapper 'Mapper|BaseObject|None' does not
have a mapped_table specified. (Are you using the return value of
table.create()? It no longer has a return value.)

Is there a way to tell SQLAlchemy to treat BaseObject like a non-
mapped-class? I tried using ORMBase as mixin to TestEntity (so
BaseObject extends object and TestEntity extends BaseObject and
ORMBase), but now I get a

sqlalchemy.exc.ArgumentError: Mapper Mapper|TestEntity|tests could not
assemble any primary key columns for mapped table 'tests'

so I guess that maybe I'm going down the wrong road.. Am I doing
something that Declarative doesn't like? :) Should I try Elixir
instead?

Many thanks for your time!

a...@svilendobrev.com

unread,
Sep 29, 2008, 10:54:54 AM9/29/08
to sqlal...@googlegroups.com
i dont know if elixir has such 'attribute/behaviour injectors', i have
DBCOOK_no_mapping=True in dbcook.sf.net that does that. the machinery
behdin it is soewhat tricky (x in class.__dict__ and not in
base_class.__dict__ etc stuff)

u may try your stuff as mixin, that may or may not work.

Gaetan de Menten

unread,
Sep 29, 2008, 11:20:12 AM9/29/08
to sqlal...@googlegroups.com

I don't know whether this is currently possible with Declarative or
not. In the case it isn't, patching Declarative should be quite easy
(but I don't know if such a patch would be accepted or not). If you
don't want to go down that route, Elixir does support that pattern.

--
Gaëtan de Menten
http://openhex.org

Joril

unread,
Sep 29, 2008, 12:04:03 PM9/29/08
to sqlalchemy
> I don't know whether this is currently possible with Declarative or
> not. In the case it isn't, patching Declarative should be quite easy
> (but I don't know if such a patch would be accepted or not).

I see.. I'll wait a bit then, maybe one of the developers will tell us
if it'd be acceptable :)

> If you don't want to go down that route, Elixir does support that pattern.

Do you mean these
http://elixir.ematia.de/trac/wiki/FAQ#HowdoIaddfunctionalitytoallmyentitiestothebaseclass
http://elixir.ematia.de/trac/wiki/FAQ#HowdoIprovideadifferentbaseclassthanEntity
?

The comment "Note that in this case you'll lose all default methods
provided by the Entity class" makes me think that extending Entity
isn't supported even in Elixir, have I got it wrong?
Thanks again!

Michael Bayer

unread,
Sep 29, 2008, 12:04:21 PM9/29/08
to sqlal...@googlegroups.com

the "Column" objects that are present on each declarative class are
unique to that class, so the creation of those three Column objects
would have to occur for each class. This suggests that the correct
approach would be to extend the declarative metaclass to provide this
behavior:

from sqlalchemy import *
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base

class MyDefaults(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
dict_['id'] = Column(Integer, primary_key=True)
dict_['creation_time'] = Column(DateTime)
dict_['modify_time'] = Column(DateTime)
return DeclarativeMeta.__init__(cls, classname, bases, dict_)

Base = declarative_base(metaclass=MyDefaults)

class TestEntity(Base):
__tablename__ = 'test'
value = Column(String)

print TestEntity.id == 5
print TestEntity.creation_time


Reply all
Reply to author
Forward
0 new messages