On 05/15/2017 09:27 PM, Никита Крокош wrote:
So, how should i do if I need many encumbrances for every cadastral object (flat.encumrances, building.encumbrances, ...etc).

If I get it correctly, I need something like:

class iCadastralObject(Base):

     __abstract__ =True
     def __init__(self, cadastral_region, cadastral_district, cadastral_block, 
cadastral_object):
         self.cadastral_region = cadastral_region
         self.cadastral_district = cadastral_district
         self.cadastral_block = cadastral_block
         self.cadastral_object = cadastral_object

     # this is a combined PK
cadastral_region = Column(Integer, primary_key=True, index=True)
     cadastral_district = Column(Integer, primary_key=True, index=True)
     cadastral_block = Column(Integer, primary_key=True, index=True)
     cadastral_object = Column(Integer, primary_key=True, index=True)

     @declared_attr
def encumbrances(self):
         return relationship("iEncumbrance")

class Building(iCadastralObject):
     __tablename__ ='building'

class Flat(iCadastralObject):
     __tablename__ ='flat'

class Construction(iCadastralObject):
     __tablename__ ='construction'

class iEncumbrance(Base):
     __tablename__ ='iencumbrance'

id = Column(Integer, primary_key=True, index=True)

     def __init__(self, cadastral_object):
         self.parent_cadastral_region = cadastral_object.cadastral_region
         self.parent_cadastral_district = cadastral_object.cadastral_district
         self.parent_cadastral_block = cadastral_object.cadastral_block
         self.parent_cadastral_object = cadastral_object.cadastral_object

     # FK fields
parent_cadastral_region = Column(Integer, nullable=False)
     parent_cadastral_district = Column(Integer, nullable=False)
     parent_cadastral_block = Column(Integer, nullable=False)
     parent_cadastral_object = Column(Integer, nullable=False)


What is the code I need to make Flat.encumbrances, etc work. Should I write custom query in a iCadastralObject class? Something like encumbrances = session.query(iEncumbrance).__filter__...? I guess the example is pretty straightforward, can you supply me with some code I should use.


And if I have for example 10 child classes, in this cade i will have a lot of boilerplate code right?

OK so lets look at the tables. you have these three (and more) tables "building" "flat" "construction". all of them can have a collection of "encumbrances". However the tables don't otherwise share anything (e.g. a common table they all join on or something). We call this the "polymorphic association" or more recently the "generic association" pattern. In frameworks like Django, they do this using a thing they call "GenericForeignKey". I've written a lot about this, and in SQLAlchemy we have an example suite illustrating a variety of recipes for implementing this - see http://docs.sqlalchemy.org/en/latest/orm/examples.html#module-examples.generic_associations.

My favorite pattern here is "table per association": http://docs.sqlalchemy.org/en/latest/_modules/examples/generic_associations/table_per_association.html . This would let you keep all the encumbrances in one big table, but makes querying from each of your "building" etc. tables very simple. People are afraid of this pattern because it creates a lot of tables. But we aren't dealing with those manually, the maintenance of tables is automated by SQLAlchemy (and potentially Alembic if you're using that too).





вторник, 16 мая 2017 г., 9:41:02 UTC+10 пользователь Mike Bayer написал:

    when you use concrete inheritance, you now have three tables: building,
    flat, construction.   If you'd like these to each have a
    relationship to
    iencumbrance, that's three separate foreign key constraints.  Given the
    four-column primary key, you'd need to have twelve columns total on
    iencumbrance and three constraints.   You cannot have a relationship
    from the "abstract" class alone, this class does not actually
    correspond
    to any table.

    Overall, if you do not need to emit a query of this form:

    objects = session.query(iCastradalObject).filter(...).all()

    then you should not use concrete inheritance.  you should map
    building /
    flat / construction alone.  if you'd like them to all have common
    features, use iCastradalObject as you are and add the __abstract__
    flag,
    don't actually use AbstractConcreteBase.   Concrete inheritance is
    almost never used.



    On 05/15/2017 07:03 PM, Никита Крокош wrote:
     > This is a duplicate from:
     >
    
http://stackoverflow.com/questions/43972912/abstract-table-concrete-inheritance-could-not-determine-join-condition-between
    
<http://stackoverflow.com/questions/43972912/abstract-table-concrete-inheritance-could-not-determine-join-condition-between>

     > I've got following example code:
     >
     > models.py
     > |
     > classCadastralObject(Base):
     >          __tablename__ ='cadastral_object'
     >
    
def__init__(self,cadastral_region,cadastral_district,cadastral_block,cadastral_object):

     > self.cadastral_region =cadastral_region
     > self.cadastral_district =cadastral_district
     > self.cadastral_block =cadastral_block
     > self.cadastral_object =cadastral_object
     >
     > # this is a combined PK
     >          cadastral_region
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_district
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_block
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_object
    =Column(Integer,primary_key=True,index=True)
     >
     >          encumbrances =relationship("Encumbrance")
     >
     > classEncumbrance(Base):
     >          __tablename__ ='encumbrance'
     >          id =Column(Integer,primary_key=True,index=True)
     > def__init__(self,cadastral_object):
     > self.parent_cadastral_region =cadastral_object.cadastral_region
     > self.parent_cadastral_district =cadastral_object.cadastral_district
     > self.parent_cadastral_block =cadastral_object.cadastral_block
     > self.parent_cadastral_object =cadastral_object.cadastral_object
     >
     > # FK fields
     >          parent_cadastral_region =Column(Integer,nullable=False)
     >          parent_cadastral_district =Column(Integer,nullable=False)
     >          parent_cadastral_block =Column(Integer,nullable=False)
     >          parent_cadastral_object =Column(Integer,nullable=False)
     >
     >          parent_object =relationship(CadastralObject)
     >          __table_args__ =(ForeignKeyConstraint(
     > [
     >                  parent_cadastral_region,
     >                  parent_cadastral_district,
     >                  parent_cadastral_block,
     >                  parent_cadastral_object],
     > [
     > CadastralObject.cadastral_region,
     > CadastralObject.cadastral_district,
     > CadastralObject.cadastral_block,
     > CadastralObject.cadastral_object]),
     > {}
     > )
     > |
     >
     > this code works as intended:
     >
     > main.py
     >
     > |
     >      c =CadastralObject(1,2,3,4)
     >      session.add(c)
     >      e =Encumbrance(c)
     >      session.add(e)
     >      session.commit()
     > print(c.encumbrances)
     > print(e.parent_object)
     > |
     >
     >
     > results:
     >
     > |
     > [<app.models.Encumbranceobjectat 0x000001C9B820BCC0>]
     > <app.models.CadastralObjectobjectat 0x000001C9B820BB00>
     > |
     >
     >
     > however, when I'm trying convert my code to Concrete Inheritance:
     >
     > imodels.py
     >
     > |
     > classiCadastralObject(AbstractConcreteBase,Base):
     >
     >
    
def__init__(self,cadastral_region,cadastral_district,cadastral_block,cadastral_object):

     > self.cadastral_region =cadastral_region
     > self.cadastral_district =cadastral_district
     > self.cadastral_block =cadastral_block
     > self.cadastral_object =cadastral_object
     >
     > # this is a combined PK
     >          cadastral_region
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_district
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_block
    =Column(Integer,primary_key=True,index=True)
     >          cadastral_object
    =Column(Integer,primary_key=True,index=True)
     >
     > @declared_attr
     > defencumbrances(self):
     > returnrelationship("iEncumbrance")
     >
     >
     >
     > classBuilding(iCadastralObject):
     >          __tablename__ ='building'
     >
     >          __mapper_args__ ={
     > 'polymorphic_identity':'building',
     > 'concrete':True
     > }
     >
     > @declared_attr
     > defencumbrances(self):
     > returnrelationship("iEncumbrance")
     >
     >
     > classFlat(iCadastralObject):
     >          __tablename__ ='flat'
     >
     >          __mapper_args__ ={
     > 'polymorphic_identity':'flat',
     > 'concrete':True
     > }
     >
     > @declared_attr
     > defencumbrances(self):
     > returnrelationship("iEncumbrance")
     >
     >
     > classConstruction(iCadastralObject):
     >          __tablename__ ='construction'
     >
     >          __mapper_args__ ={
     > 'polymorphic_identity':'construction',
     > 'concrete':True
     > }
     >
     >
     > classiEncumbrance(Base):
     >          __tablename__ ='iencumbrance'
     >
     >          id =Column(Integer,primary_key=True,index=True)
     >
     > def__init__(self,cadastral_object):
     > self.parent_cadastral_region =cadastral_object.cadastral_region
     > self.parent_cadastral_district =cadastral_object.cadastral_district
     > self.parent_cadastral_block =cadastral_object.cadastral_block
     > self.parent_cadastral_object =cadastral_object.cadastral_object
     >
     > # FK fields
     >          parent_cadastral_region =Column(Integer,nullable=False)
     >          parent_cadastral_district =Column(Integer,nullable=False)
     >          parent_cadastral_block =Column(Integer,nullable=False)
     >          parent_cadastral_object =Column(Integer,nullable=False)
     >
     >          parent_object =relationship(iCadastralObject)
     >
     >          __table_args__ =(ForeignKeyConstraint(
     > [
     >                  parent_cadastral_region,
     >                  parent_cadastral_district,
     >                  parent_cadastral_block,
     >                  parent_cadastral_object],
     > [
     >                  iCadastralObject.cadastral_region,
     >                  iCadastralObject.cadastral_district,
     >                  iCadastralObject.cadastral_block,
     >                  iCadastralObject.cadastral_object]),
     > {}
     > )
     > |
     >
     >
     >
     >
     > I'm getting an error on "from app.imodels import Building"
     >
     > |
     >      sqlalchemy.exc.NoForeignKeysError:Couldnotdetermine join
    condition
     > between parent/child tables on relationship
     > iCadastralObject.encumbrances -there are noforeign keys linking
    these
     > tables.Ensurethat referencing columns are associated witha
     > ForeignKeyorForeignKeyConstraint,orspecify a
    'primaryjoin'expression.
     > |
     >
     >
     >
     >
     >
     >
     > --
     > 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
    <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+...@googlegroups.com <javascript:>
     > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>.
     > To post to this group, send email to sqlal...@googlegroups.com
    <javascript:>
     > <mailto:sqlal...@googlegroups.com <javascript:>>.
     > Visit this group at https://groups.google.com/group/sqlalchemy
    <https://groups.google.com/group/sqlalchemy>.
     > For more options, visit https://groups.google.com/d/optout
    <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 <mailto:sqlalchemy+unsubscr...@googlegroups.com>. To post to this group, send email to sqlalchemy@googlegroups.com <mailto: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