2015-11-23 19 views
5

I seguenti oggetti e relazioni sono definiti. Questo è in realtà un caso abbastanza semplice, e sto fornendo tutti questi campi solo per mostrare perché credo che l'inalazione e l'anestesia da iniezione dovrebbero essere definite da due classi diverse.associazioni di classi multiple/suddivise in sqlalchemy

class InhalationAnesthesia(Base): 
    __tablename__ = "inhalation_anesthesias" 
    id = Column(Integer, primary_key=True) 
    anesthetic = Column(String) 
    concentration = Column(Float) 
    concentration_unit = Column(String) 
    duration = Column(Float) 
    duration_unit = Column(String) 


class TwoStepInjectionAnesthesia(Base): 
    __tablename__ = "twostep_injection_anesthesias" 
    id = Column(Integer, primary_key=True) 
    anesthetic = Column(String) 
    solution_concentration = Column(Float) 
    solution_concentration_unit = Column(String) 
    primary_dose = Column(Float) 
    primary_rate = Column(Float) 
    primary_rate_unit = Column(String) 
    secondary_rate = Column(Float) 
    secondary_rate_unit = Column(String) 

class Operation(Base): 
    __tablename__ = "operations" 
    id = Column(Integer, primary_key=True) 
    anesthesia_id = Column(Integer, ForeignKey('inhalation_anesthesias.id')) 
    anesthesia = relationship("InhalationAnesthesia", backref="used_in_operations") 

avrei, però, come per definire l'attributo anestetico della classe Operation in modo tale che qualsiasi oggetto Operation può puntare a un oggetto o un oggetto TwoStepInjectionAnesthesiaInhalationAnesthesia.

Come posso farlo?

risposta

6

Ti suggerisco di utilizzare l'ereditarietà. E 'molto, molto ben spiegato nei documenti SQLAlchemy here e here

La mia raccomandazione è quella di creare una classe Anesthesia e fare sia InhalationAnesthesia e TwoStepInjectionAnesthesia ereditano da essa. E 'la tua chiamata a decidere quale tipo di utilizzo ereditarietà delle tabelle:

  • singola tabella ereditarietà
  • ereditarietà concreta delle tabelle
  • tabella unita eredità

Le forme più comuni di eredità sono single e tabella unita, mentre l'eredità concreta presenta più sfide configurazionali.


Per il vostro caso sto asuming unito ereditarietà delle tabelle è l'elezione:

class Anesthesia(Base) 
    __tablename__ = 'anesthesias' 
    id = Column(Integer, primary_key=True) 
    anesthetic = Column(String) 
    # ... 
    # every common field goes here 
    # ... 
    discriminator = Column('type', String(50)) 
    __mapper_args__ = {'polymorphic_on': discriminator} 

Lo scopo di discriminator campo:

... è quella di agire come discriminatore e memorizza un valore che indica il tipo di oggetto rappresentato all'interno della riga. La colonna può essere di qualsiasi tipo di dati, sebbene stringa e intero siano i più comuni.

s' __mapper_args__polymorphic_on chiave che definiscono l'uso sul campo come discriminatore. Nelle classi figlie (sotto), identità_identità_pellicola, definire il valore che verrà memorizzato nella colonna del discriminatore polimorfico per le istanze della classe.

class InhalationAnesthesia(Anesthesia): 
    __tablename__ = 'inhalation_anesthesias' 
    __mapper_args__ = {'polymorphic_identity': 'inhalation'} 
    id = Column(Integer, ForeignKey('anesthesias.id'), primary_key=True) 
    # ... 
    # specific fields definition 
    # ... 


class TwoStepInjectionAnesthesia(Anesthesia): 
    __tablename__ = 'twostep_injection_anesthesias' 
    __mapper_args__ = {'polymorphic_identity': 'twostep_injection'} 
    id = Column(Integer, ForeignKey('anesthesias.id'), primary_key=True) 
    # ... 
    # specific fields definition 
    # ... 

Infine la classe Operation può fare riferimento alla tabella padre Anesthesia con un rapporto tipico:

class Operation(Base): 
    __tablename__ = 'operations' 
    id = Column(Integer, primary_key=True) 
    anesthesia_id = Column(Integer, ForeignKey('anesthesias.id')) 
    anesthesia = relationship('Anesthesia', backref='used_in_operations') 

Spero che questo è quello che stai cercando.

+0

Quindi, utilizzando questa configurazione, dovrei essere in grado di fare riferimento a entrambi gli oggetti "InhalationAnesthesia" e "TwoStepInjectionAnesthesia" in "Operation.anesthesia'? Userebbe 'Operation.anesthesia = [TwoStepInjectionAnesthesia (..), InhalationAnesthesia (..), Inhalationanesthesia (..)]' rovinare tutto? – TheChymera

+0

@TheChymera Sì e Sì. Nell'esempio fornito un'istanza di 'Operation' farà riferimento a un solo oggetto' Anesthesia'. Se ti serve una lista, dovresti cambiare un po 'il codice. –

+0

Un'altra cosa, qual è il vantaggio di utilizzare l'impostazione di cui sopra (oltre ad essere organizzata leggermente meglio sul lato Python)? la tabella sql effettiva che viene generata contiene determinati tipi di colonna solo per le righe con determinati descrittori? (quindi risparmiando spazio sul disco?) – TheChymera