Hi folks,
A need to build a one-to-many relation with a mixin class. It works if I
just mix only one class (TaskableClassA in the example), the second class
that I mix with the TaskMixin (TaskableClassB) will produce the following
error:
sqlalchemy.exc.ArgumentError: Error creating backref 'task_of' on
relationship 'TaskableClassB.tasks': property of that name exists on mapper
'Mapper|Task|Tasks'
I find the error message meaningful but can't create anything that will not
produce this situation. Any idea?
here is the simplified version of my code (you can copy/paste to test it):
Basically there is the base class SimpleEntity then the mixin class
TaskMixin, and then two other classes (TaskableClassA, TaskableClassB)
deriving from the SimpleEntity and mixed with TaskMixin.
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship, validates
from sqlalchemy.ext import declarative
from sqlalchemy.ext.declarative import declarative_base, declared_attr
Base = declarative_base()
# The Base Class
########################################################################
class SimpleEntity(Base):
__tablename__ = "SimpleEntities"
id = Column("id", Integer, primary_key=True)
entity_type = Column("db_entity_type", String(128), nullable=False)
__mapper_args__ = {
"polymorphic_on": entity_type,
"polymorphic_identity": "SimpleEntity",
}
name = Column(String(256), nullable=False)
#----------------------------------------------------------------------
def __init__(self, name=None, **kwargs):
self.name = name
########################################################################
class Task(SimpleEntity):
__tablename__ = "Tasks"
task_id = Column("id", Integer, ForeignKey("SimpleEntities.id"),
primary_key=True)
__mapper_args__ = {"polymorphic_identity": "Task",
"inherit_condition": task_id==SimpleEntity.id}
task_of_id = Column(Integer,
ForeignKey("SimpleEntities.id")
)
#----------------------------------------------------------------------
def __init__(self, task_of=None, **kwargs):
super(Task, self).__init__(**kwargs)
self.task_of = task_of
########################################################################
class TaskMixin(object): # The mixin
def __init__(self, tasks=None, **kwargs):
if tasks is None:
tasks = []
self.tasks = tasks
#----------------------------------------------------------------------
@declared_attr
def tasks(cls):
return relationship(
"Task",
primaryjoin="Tasks.c.task_of_id==SimpleEntities.c.id",
backref="task_of",
)
########################################################################
# example class 1 - defining only one class with TaskMixin doesn't create
# any problem
class TaskableClassA(SimpleEntity, TaskMixin):
__tablename__ = "TaskableAs"
__mapper_args__ = {"polymorphic_identity": "TaskableClassA"}
taskableClass_id = Column("id", Integer,
ForeignKey("SimpleEntities.id"),
primary_key=True)
#----------------------------------------------------------------------
def __init__(self, **kwargs):
super(SimpleEntity, self).__init__(**kwargs)
TaskMixin.__init__(self, **kwargs)
#######################################################################
# example class 2 - which creates the problem
class TaskableClassB(SimpleEntity, TaskMixin):
__tablename__ = "TaskableBs"
__mapper_args__ = {"polymorphic_identity": "TaskableClassB"}
taskableClass_id = Column("id", Integer,
ForeignKey("SimpleEntities.id"),
primary_key=True)
#----------------------------------------------------------------------
def __init__(self, **kwargs):
super(SimpleEntity, self).__init__(**kwargs)
TaskMixin.__init__(self, **kwargs)
a_taskable_object = TaskableClassA(name="taskable test object")
task1 = Task(name="Test Task1", task_of=a_taskable_object)
thanks...
E.Ozgur Yilmaz
Lead Technical Director
eoyilmaz.blogspot.com
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
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.