SQLAlchemy: Attribut als Klasse

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Hallo,

irgendwie bin ich zu doof, etwas entsprechendes in der SQLAlchemy - Doku zu finden:

Ich möchte ein Attribut einer SQLAlchemy Klasse nicht als Wert aus der DB repräsentieren, sondern als eigenständige Klasse, allerdings nicht als weitere SQLAlchemy Klasse ...

sowas in der Art:

Code: Alles auswählen


class Weight(object):
    # spannende Klasse zum Umrechnen von Gewichten
    pass

# Persistenz
class Person(Base):
    id = Column(Integer, primary_key=True)
    weight = Column(Numeric)
hier wird ja das Gewicht der Person als Zahlenwert aus der DB gelesen. Ich suche jetzt einen Mechanismus, der mir das Gewicht nicht als Wert sondern als eigene Klasse einsetzt. Das muss ja sowohl beim Lesen, als auch beim Speichern wieder in den Zahlenwert umgewandelt werden. Weiss jemand, wie man sowas realisieren könnte? Privates, numerisches Attribut und das öffentliche Attribut, welches die Klasse hält, über getter/setter?


Frank
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Suchst du das?

Sebastian
Das Leben ist wie ein Tennisball.
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Hallo Sebastian,

ja, das scheint eine Möglichkeit zu sein, so etwas umzusetzen. Leider ist die Dokumentation dazu nicht ganz vollständig - da hilft wohl nur ausprobieren ...

Gruß

Frank
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

So gehts:

Code: Alles auswählen

# coding: utf-8

from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.types import TypeDecorator, Numeric
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()


class Weight(object):
    
    def __init__(self, value, unit):
        self.value = value
        self.unit = unit
        
    @property
    def base_value(self):
        return self.value * 1000
    
    
class WeightType(TypeDecorator):
    
    impl = Numeric
    
    def process_bind_param(self, weight, dialect):
        return weight.base_value
    
    def process_result_value(self, value, dialect):
        return Weight(value, "g")
    
    
class Person(Base):
    
    __tablename__ = 'persons'
    
    id = Column(Integer, primary_key=True)
    name = Column(String)
    weight = Column(WeightType)
        
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight


def setup_database():
    engine = create_engine('sqlite:///memory', echo=True)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    return engine, session


def save():
    
    engine, session = setup_database()
    
    Base.metadata.bind = engine
    Base.metadata.create_all()
    
    peter = Person("Peter", Weight(70, "kg"))
    karl = Person("Karl", Weight(80, "kg"))
    jutta = Person("Jutta", Weight(65, "kg"))
    
    session.add_all([peter, karl, jutta])
    session.commit()
    

def load():
    engine, session = setup_database()
    
    Base.metadata.bind = engine
    Base.metadata.create_all()
    
    peter = session.query(Person).filter(Person.name=="Peter").first()
    
    print peter.name, peter.weight.value

    
if __name__ == "__main__":
    save()
    load()
Antworten