Oh weird, it must have gotten erased before I pressed send...whoops! On Nov 15, 2017 4:03 AM, "Simon King" <[email protected]> wrote:
> On Wed, Nov 15, 2017 at 12:10 AM, Mike Bayer <[email protected]> > wrote: > > On Tue, Nov 14, 2017 at 2:58 PM, Olaf <[email protected]> wrote: > >> Hello everybody. > >> > >> Is it possible to have the following relationships between three classes > >> (Animal, Car, Description) ? > >> > >> * An animal has an attribute description > >> * A car has an attribute description > >> * Each description contains his parent as an attribut. So parent can be > a > >> car or an animal > >> > >> Here is my code : > >> > >> from sqlalchemy import create_engine > >> from sqlalchemy.orm import sessionmaker > >> from sqlalchemy.ext.declarative import declarative_base > >> from sqlalchemy import Column, Integer, String, ForeignKey > >> from sqlalchemy.orm import relationship > >> > >> > >> Base = declarative_base() > >> > >> > >> class Description(Base): > >> __tablename__ = "descriptions" > >> id = Column(Integer, primary_key=True) > >> name = Column(String) > >> > >> > >> def __init__(self, name): > >> self.name = name > >> self.parent = None > >> > >> > >> def __repr__(self): > >> return self.name > >> > >> > >> class Animal(Base): > >> __tablename__ = "animals" > >> id = Column(Integer, primary_key=True) > >> name = Column(String) > >> id_description = Column(Integer, ForeignKey("descriptions.id"), > nullable > >> = False) > >> description = relationship("Description", backref = "parent") > >> > >> > >> def __init__(self, name): > >> self.name = name > >> > >> > >> def __repr__(self): > >> return self.name > >> > >> > >> class Car(Base): > >> __tablename__ = "cars" > >> id = Column(Integer, primary_key=True) > >> name = Column(String) > >> id_description = Column(Integer, ForeignKey("descriptions.id"), > nullable > >> = False) > >> description = relationship("Description", backref = "parent") > >> > >> > >> def __init__(self, name): > >> self.name = name > >> > >> > >> def __repr__(self): > >> return self.name > >> > >> > >> > >> > >> engine = create_engine('YOUR DATABASE', echo = True) > >> > >> > >> Base.metadata.create_all(engine) > >> > >> Session = sessionmaker(bind=engine) > >> session = Session() > >> > >> rex = Animal("Rex") > >> swift = Car("Suzuki Swift") > >> > >> d1 = Description("Rex is a good dog.") > >> d2 = Description("What a beautiful car !") > >> > >> rex.description = d1 > >> d1.parent = rex > >> swift.description = d2 > >> d2.parent = swift > >> > >> session.add(rex) > >> session.add(swift) > >> session.add(d1) > >> session.add(d2) > >> > >> session.commit() > >> > >> > >> > >> Error : > >> > >> Traceback (most recent call last): > >> File "C:\Users\user\Desktop\test.py", line 56, in <module> > >> rex = Animal("Rex") > >> File "<string>", line 2, in __init__ > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\ > instrumentation.py", > >> line 347, in _new_state_if_none > >> state = self._state_constructor(instance, self) > >> File "C:\Python34\lib\site-packages\sqlalchemy\util\langhelpers.py", > line > >> 767, in __get__ > >> obj.__dict__[self.__name__] = result = self.fget(obj) > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\ > instrumentation.py", > >> line 177, in _state_constructor > >> self.dispatch.first_init(self, self.class_) > >> File "C:\Python34\lib\site-packages\sqlalchemy\event\attr.py", line > 256, > >> in __call__ > >> fn(*args, **kw) > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\mapper.py", line > 3129, > >> in _event_on_first_init > >> configure_mappers() > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\mapper.py", line > 3019, > >> in configure_mappers > >> mapper._post_configure_properties() > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\mapper.py", line > 1810, > >> in _post_configure_properties > >> prop.init() > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\interfaces.py", > line > >> 184, in init > >> self.do_init() > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\relationships.py", > line > >> 1661, in do_init > >> self._generate_backref() > >> File "C:\Python34\lib\site-packages\sqlalchemy\orm\relationships.py", > line > >> 1851, in _generate_backref > >> (backref_key, self, m)) > >> sqlalchemy.exc.ArgumentError: Error creating backref 'parent' on > >> relationship 'Animal.description': property of that name exists on > mapper > >> 'Mapper|Description|descriptions' > >> > >> > >> It seems impossible to link the classes to the same attribute "parent" > in > >> the class "Description". Is there a solution ? > > > > > > you're attempting a pattern we call "generic association" (I've also > > called it "polymorphic association") - a single destination item that > > can be referred to by many types of objects. I've documented three > > ways of doing these, noting that one of them is a common pattern from > > the Django / Rails world, though I don't recommend that one. Unless > > you need to query for descriptions across Dogs/Cars at the same time, > > I'd go with table_per_related. The mental exercise here is being OK > > with the fact that there are more tables than you thought there would > > be. It "feels" wrong to have multiple tables with the same columns > > but there's actually nothing wrong with it at all. Your source code > > need not have any repetition in it. > > > > Here's the link to the docs: > > http://docs.sqlalchemy.org/en/latest/orm/examples.html# > module-examples.generic_associations > > Simon > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. > -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
