On Tue, Nov 14, 2017 at 2:58 PM, Olaf <bastien...@gmail.com> 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.





>
> Thank you for your help !
>
> Olaf
>
> --
> 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 sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> 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 sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to