2015-11-23 7 views
5

Mam zdefiniowane następujące obiekty i relacje. Jest to w rzeczywistości dość prosty przypadek i dostarczam wszystkie te pola tylko po to, aby pokazać, dlaczego sądzę, że wdychanie i znieczulenie przez wstrzyknięcie powinny być określone przez dwie różne klasy.skojarzenia klasy wiele/podzielone w 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") 

bym jednak chciał zdefiniować znieczulający atrybut klasy Operation w taki sposób, że każda Operation obiekt może wskazywać albo TwoStepInjectionAnesthesia obiekt lub przedmiot InhalationAnesthesia.

Jak mogę to zrobić?

Odpowiedz

6

Proponuję ci użyć dziedziczenia. To bardzo, bardzo dobrze wyjaśnione w docs sqlalchemy here i here

Moja rada jest taka, aby utworzyć klasę Anesthesia i uczynić zarówno InhalationAnesthesia i TwoStepInjectionAnesthesia Dziedziczy z niego. To twoja decyzja, aby zdecydować, jaki rodzaj zastosowania tabeli spadków:

  • pojedyncza tabela dziedziczenie
  • stół beton dziedziczenie
  • dołączył tabela dziedziczenie

Najczęstsze formy dziedziczenia są jedno- i dołączył do tabeli, a dziedziczenie betonu przedstawia więcej wyzwań konfiguracyjnych.


Twoim przypadku mam asuming dołączył tabela dziedziczenie jest wybór:

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} 

Celem discriminator polu:

... ma działać jako dyskryminator i przechowuje wartość wskazującą typ obiektu reprezentowanego w wierszu. Kolumna może być dowolnego typu danych, ale ciąg i liczba całkowita są najczęściej spotykane jako .

__mapper_args__ „s polymorphic_on klucz określić, które wykorzystują pole jako dyskryminatora. W klasach podrzędnych (poniżej) klucz polymorphic_identity definiuje wartość, która będzie przechowywana w kolumnie polimorficznego dyskryminatora dla wystąpień klasy.

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 
    # ... 

Wreszcie klasa Operation mogą odwoływać się do tabeli nadrzędnej Anesthesia z typowej relacji:

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') 

nadzieję, że to, czego szukasz.

+0

Używając tego ustawienia powinienem móc odwoływać się do obiektów "InhalationAnesthesia" i "TwoStepInjectionAnesthesia' w" Operation.anesthesia "? Używanie 'Operation.anesthesia = [TwoStepInjectionAnesthesia (..), InhalationAnesthesia (..), Inhalationanesthesia (..)]' coś zepsuć? – TheChymera

+0

@ TheChymera Tak i tak. W podanym przykładzie instancja 'Operation' odwoła się tylko do jednego obiektu' Anesthesia'. Jeśli chcesz, aby była to lista, powinieneś nieco zmienić kod. –

+0

Jeszcze jedna rzecz, jaka jest zaleta korzystania z powyższej konfiguracji (poza nieco lepszą organizacją na końcu Pythona)? czy rzeczywista tabela sql, która zostanie wygenerowana, zawiera określone typy kolumn tylko dla wierszy z określonymi dyscrminatorami? (w ten sposób oszczędzając miejsce na dysku?) – TheChymera

Powiązane problemy