2015-12-22 9 views
20

Quindi, ci sono alcune domande e risposte che toccano questo problema ma non riesco a riconciliarle esattamente con quello che sto cercando di ottenere.SQLALchemy Configurazione della relazione di molti a molti modelli con modelli polimorfici

Here, here e here

Ho una serie di modelli che sono auto-referenziale ed ereditato. Questo è il design di base.

class BaseUser(db.Model): 
    id = db.Column(db.Integer, primary_key=True, nullable=False) 
    org = db.Column(db.Boolean, default=False, nullable=False) 
    # Shared Fields 
    __mapper_args__ = { 
     'polymorphic_on': org, 
    } 

class Customer(BaseUser): 
    # Customer Fields 
    __mapper_args__ = { 
     'polymorphic_identity': 0 
    } 

class Organization(BaseUser): 
    # Organization Fields 
    __mapper_args__ = { 
     'polymorphic_identity': 1 
    } 

class CustomerOrganization(db.Model): 
    user_id = db.Column(db.ForeignKey('customer.id', ondelete=CASCADE, onupdate=CASCADE), primary_key=True, nullable=False) 
    org_id = db.Column(db.ForeignKey('customer.id', ondelete=CASCADE, onupdate=CASCADE), primary_key=True, nullable=False) 

Ho provato un paio di modi diversi per creare un "org" e un rapporto di "membri" su ciascuno di questi tipi. Qualche consiglio su come definire gli attributi relationsihp()?

risposta

5

È possibile utilizzare le proprietà primaryjoin e secondaryjoin. La documentazione pertinente è here.

Esempio:

customer_organization = Table(
    'base_user_customer_organization', ModelBase.metadata, 
    Column('user_id', Integer, ForeignKey('base_user.id')), 
    Column('org_id', Integer, ForeignKey('base_user.id')) 
) 


class BaseUser(ModelBase): 
    __tablename__ = 'base_user' 

    id = Column(Integer, primary_key=True, nullable=False) 
    org = Column(Boolean, default=False, nullable=False) 
    # Shared Fields 
    __mapper_args__ = { 
     'polymorphic_on': org, 
    } 
    customers = relationship(
     "BaseUser", 
     backref=backref('organization', order_by=id), 
     secondary=customer_organization, 
     primaryjoin=id==customer_organization.c.org_id and org==True, 
     secondaryjoin=id==customer_organization.c.user_id and org==False 
    ) 


class CustomerUser(BaseUser): 
    # Customer Fields 
    __mapper_args__ = { 
     'polymorphic_identity': False 
    } 


class OrganizationUser(BaseUser): 
    # Organization Fields 
    __mapper_args__ = { 
     'polymorphic_identity': True 
    } 

E prova:

sql = sqldb.get_session() 
customer1 = sqldb.system.CustomerUser() 
sql.add(customer1) 
customer2 = sqldb.system.CustomerUser() 
sql.add(customer2) 
organization = sqldb.system.OrganizationUser() 
organization.customers = [customer1, customer2] 
sql.add(organization) 
sql.commit() 
# function prints all table data 
print get_sql_table_data(sqldb.system.BaseUser) 
print organization.customers 
print customer1.organization 
print customer2.organization 

uscita:

[{'org': False, 'id': 1}, {'org': False, 'id': 2}, {'org': True, 'id': 3}] 
[<CustomerUser(id=1, org=False)>, <CustomerUser(id=2, org=False)>] 
[<OrganizationUser(id=3, org=True)>] 
[<OrganizationUser(id=3, org=True)>] 
+0

+1 come prima della singola tabella polimorfico tiene le due classi, qui la relazione molti-molti la tabella è esposta come una proprietà di raccolta usando back-ref che penso sia standard – jayprich

Problemi correlati