[sqlalchemy] backref

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Code: Alles auswählen

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child", backref=backref("parent", uselist=False))

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
Bei meinem Verständnis handelt es sich hierbei um eine unidirektionale one-to-one Beziehung. "Parent" kennt sein "Child", aber "Child" weiß nichts über "Parent" oder ob es überhaupt ein "Parent" hat. Korrekt?

Aber was macht "backref" hier? Das ist mir nicht klar. Die Doku hierzu verstehe ich leider auch nicht. Zuviel "Fachsprache" für mein bescheidenes Englisch.

In meinem Fall ist die Existenz von Child-Instanzen unabhängig von den Parents. Child kann auch ohne Parent existieren.
BlackJack

@MoonKid: Das ist eine bidirektionale 1:1 Beziehung. Und genau das macht das `backref()` hier („back reference”, Rückverweis). Das sorgt dafür das `Child` ein Attribut mit dem Namen `parent` bekommt. Und das `uselist=False` dass dieser Rückverweis keine Liste von `Parent`-Objekten ist, sondern das es genau *eins* gibt. Das kann dann aber auch `None` sein, weil die Spalte `child_id` ja auch NULL-Werte enthalten darf.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Ok, verstehe. Dann werden uni-direktionale 1:1 Beziehung in der Doku gar nicht erklärt. Bin ich der einzige der sowas braucht? ;)

Schreibe ich in dem Fall einfach

Code: Alles auswählen

child = relationship("Child")
Wirkt beinah zu einfach.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@MoonKid: jup. Wenn Du keine backref brauchst, gibts Du einfach keine an.
BlackJack

@MoonKid: Eigentlich gibt es im relationalen Modell ja keine unidirektionalen Beziehungen. Du kannst Dich halt nur entscheiden eine Richtung nicht als Attribut zur Verfügung zu stellen. Die meisten Leute wollen dieses Attribut halt haben, darum beschreibt das Tutorial halt diesen Normalfall als erstes. Andererseits werden unter dem Abschnitt „Basic Relationship Patterns” doch alle Möglichkeiten durchgespielt und mit Beispielen gezeigt und in „Linking Relationships with Backref” wird speziell `backref()` noch mal im Detail beleuchtet.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Ich denke eher Objektorientiert und entwerfe meine Datenmodelle entsprechend. Jede zusätzliche Referenz bzw. Richtung verkompliziert das Model, erhöht dadurch die Fehleranfälligkeit und den Wartungsaufwand. Ich setze hier auf eine relationale DB, weil ich bisher keine passendes ODBMS mit Pythonanbindung finden konnte. Es ist grundsätzlich auch zu "exotisch". Der Community-Support bei RDMBS und Python ist einfach besser, weil hier die Community mehr Erfahrung hat. Bei ODBMS kann mir kaum jemand helfen. ;)

Ja, die Doku. Wie gesagt: mein English. Hab es zweimal gelesen und nicht verstanden, obwohl ich die Wörter durchaus kenne. So ein Thema muss man auf Deutsch schon langsam und konzentriert lesen, um es erfassen zu können.
BlackJack

@MoonKid: Mit dem Ansatz einen reinen OOP-Entwurf zu machen und den dann auf ein RDBMS abzubilden habe ich eher schlechte Erfahrungen gemacht. Das kann funktionieren, muss es aber nicht. Nicht alles was man sich bei OOP an Objektgraphen überlegen kann, lässt sich wirklich gut in das relationale Modell pressen.

*Die* Objektdatenbank bei Python dürfte die Zope Object Database sein. Ist dann aber eine reine Python-Veranstaltung.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Soweit ich sehe gibt es keine standarditiserten Zugriffsmöglichkeiten (z.B. ODBC) auf eine ZODB?
BlackJack

@MoonKid: Was sollte der Sinn davon sein? Die Datenbank speichert *Python*-Objekte, mit einer anderen Sprache will man da sowieso nicht dran gehen.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

BlackJack hat geschrieben:@MoonKid: Was sollte der Sinn davon sein? Die Datenbank speichert *Python*-Objekte, mit einer anderen Sprache will man da sowieso nicht dran gehen.
Sowie man RDBMS-Daten auf Objekte mappen kann, geht es andersherum auch. Schau dir mal FastObjects (ehemals Poet DB) an. Feines Teil, aber closed und unverschämt teuer. ;)
BlackJack

@MoonKid: Wie gesagt, meiner Erfahrung nach geht das nicht wirklich gut einen beliebigen OOP-Entwurf in das relationale Modell zu pressen.

Man würde da wahrscheinlich auch deutlich mehr Arbeit hineinstecken müssen wenn man so eine Abbildung haben möchte, und irgendwie deklarieren was, wie auf eine RDBMS-Ansicht abgebildet werden soll. In die ZODB kann man nahezu beliebige Python-Objekte speichern ohne irgendein Schema deklarieren zu müssen. Einzig die Objekte die als Basis für Transaktionen dienen sollen müssen von einer `Persistent`-Klasse erben. Welche Attribute die haben, oder welche Attribute deren Attribute haben ist völlig egal und man kann auch zur Laufzeit neue hinzufügen oder wegnehmen. Eben wie man das von Python-Objekten so gewohnt ist.
Antworten