Hallo mal wieder,
bezüglich meiner Miethausverwaltung (aktuelle Version (auch noch ziemlich unterentwickelt) liegt hier) suche ich nach einer Möglichkeit, vom Nutzer angelegte Daten auch dauerhaft und sicher speichern zu können. Nach einer etwas krampfigen Einarbeit in sqlite funktioniert mein Testskript (hier) auch endlich ungefähr so, wie ich mir das vorstelle.
Nur, später gibts ja ungefähr zigmillionen Objekte, Blumen oder Mieter, was auch immer. Wenn ich dann aber sowas anfragen will, wie "alle Mieter anzeigen, die zu spät Miete gezahlt haben" muss ich ja, um auf die entsprechenden Eigenschaften der gespeicherten Objekte zugreifen zu können, sämtliche Datenbankeinträge erst mal in Objekte umwandeln, um dann in denen wiederum nach den gefragten Eigenschaften zu suchen.
Das würde doch aber für eine relativ hohe Speicherbelastung sorgen und kommt mir auch irgendwie unsinnig vor.
Dazu kommt auch noch, daß z.B. mein "Wohnung"-Objekt eine Liste aller jemals eingezogenen Mieter enthält, welche man ja wieder nur über Umwege in der DB abspeichern könnte.
Jetzt aber nur direkt mit Datenbankeintragungen zu arbeiten, finde ich dann auch wieder inkonsequent, ich will doch meine tollen Methoden benutzen (siehe Miethauscode), wie z.B. "Mieter in Wohnung einziehen lassen".
Ich weiß grad irgendwie nicht, in welche Richtung ich jetzt weitergehen soll. Mein Datenbankansatz kommt mir nicht schlüssig vor. Meine Miethausverwaltung aber wenigstens son bißchen. Oder sollte ich letztere unter dem Aspekt der Datenspeicherung besser völlig anders aufbauen ? Wie macht man sowas ?
Mit SQlite Objekte speichern, was bringt das eigentlich ?
- Defnull
- User
- Beiträge: 778
- Registriert: Donnerstag 18. Juni 2009, 22:09
- Wohnort: Göttingen
- Kontaktdaten:
Was du suchst ist ein ORM (Object Relational Mapper) also den Kleber zwischen Objekten und Tabellarischen (rationalen) Datenbanken. Google mal nach SQLAlchemy.
Bottle: Micro Web Framework + Development Blog
mhm, hat mir cofi auch schon vorgeschlagen, bleibt das Problem des SQL-Servers. Kann ich den prinzipiell so in eine Installationsroutine verpacken, daß der Endnutzer, wenn er denn dann mein tolles Programm installiert, damit nix zu tun hat ?
Die `sqlite3`-Bibliothek sollte bei Windows zum Lieferumfang von Python gehören und bei Linux ist's halt eine Abhängigkeit, die über die Paketverwaltung automatisch nachgezogen wird.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Nein, andersrum. SQLAlchemy ist eine Abstraktionsschicht ueber der Datenbank, damit du dich nicht damit rumschlagen musst.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
SQLAlchemy ist pure Python, d.h. du musst das sogar nur in den Ordner deines Programms legen. Die Datenbank kannst du auch so bedienen, allerdings nicht um damit ganze Objekte zu speichern, du muesstest die vorher serialisieren.
Den ganzen Kram erledigt SQLAlchemy.
Bevor du aber eine Datenbank damit fuettern kannst, solltest du dich erstmal in SQLAlchemy einlesen
Den ganzen Kram erledigt SQLAlchemy.
Bevor du aber eine Datenbank damit fuettern kannst, solltest du dich erstmal in SQLAlchemy einlesen

Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- Defnull
- User
- Beiträge: 778
- Registriert: Donnerstag 18. Juni 2009, 22:09
- Wohnort: Göttingen
- Kontaktdaten:
Mit dem Unterschied, das SQLAlchemy nicht einfach alles durch pickle jagt, sondern Datenbanken so verwendet, wie sie gedacht sind.cofi hat geschrieben:... du muesstest die vorher serialisieren. Den ganzen Kram erledigt SQLAlchemy.
Grob zusammengefasst funktioniert das so:
Jedes von SQLAlchemy gemappte Objekt ist einer Tabelle in der Datenbank zugeordnet. Jedes Attribut des Objektes ist eine Spalte in der passenden Tabelle. Wenn du ein Objekt lädst, baut es SA aus den Daten in der Datenbank für dich zusammen. Wenn du es veränderst und dann speicherst, werden die Daten wieder in die Datenbank geschrieben. Da jedes Attribut der Objekte in einer eigenen Spalte steht, kann man darin suchen. Du kannst dir von SA also z.B. alle Blumen geben lassen, die rot sind, ohne jede einzelne Blume laden zu müssen.
Wenn du Assoziationen richtig definierst, kannst du auch z.B. eine Wohnung laden und von da aus direkt auf die Mieter der Wohnung zu greifen. SA weist dann nämlich, welche Mieter zu welcher Wohnung gehören.
Allerdings sollte man SQL oder wenigstens das Prinzip von relationalen Datenbanken verstanden und verinnerlicht haben, bevor man sich an SQLAlchemy wagt. Einfach ist dieses ORM System nämlich nicht. Dafür ist es allerdings mächtig
Bottle: Micro Web Framework + Development Blog
Ich würde so weit gehen und sagen, SQLalchemy ist viel zu kompliziert. Einfacher ist da z.B. http://www.sqlobject.org/ oder http://autumn-orm.org/.
Komplett von einer DB zu abstrahieren ist IMHO auch nicht der richtige Weg. Eigentlich ist Microsoft LINQ-Ansatz richtig. Von Nathan Sobo habe ich neulich eine Talk über eine JavaScript-Bibliothek gesehen, die einem Joins und Projections auf JavaScript-Objekten erlaubte, also den Kern einer RDB nicht versucht hat zu verstecken sondern im Gegenteil anzubieten. So etwas könnte man natürlich genauso gut auch in Python benutzen.
Stefan
Komplett von einer DB zu abstrahieren ist IMHO auch nicht der richtige Weg. Eigentlich ist Microsoft LINQ-Ansatz richtig. Von Nathan Sobo habe ich neulich eine Talk über eine JavaScript-Bibliothek gesehen, die einem Joins und Projections auf JavaScript-Objekten erlaubte, also den Kern einer RDB nicht versucht hat zu verstecken sondern im Gegenteil anzubieten. So etwas könnte man natürlich genauso gut auch in Python benutzen.
Stefan
jut, dann hab ich mich also zumindest schon mal bruchstückhaft in diesen Chemiebaukasten eingelesen. Das Tutorial entspricht gott sei Dank auch zeimlich genau meinem ersten Konstrukt, nämlich Haus und seine Wohnungen. Funktioniert auch so, wie es soll. Die Herangehensweise gefällt mir so eigentlich ganz gut. (hier mal schaun, da ist er, der Code)
Soweit hab ich die Arbeitsweise auch grob verstanden.
Erstes Problem: Laut Tutorial kann man ja die deklarative Methode benutzen, um die entsprechende Tabelle für das jeweilige Objekt anzulegen. Das versteh ich da so, daß ich mir diese anfängliche Schreiberei von Zeile 10 bis 24 eigentlich sparen kann, kommt ja alles nochmal in der Klasse. Geht bei mir nur irgendwie nicht, wenn das da nicht steht, legt der Kollege keine Tabellen an.
Zweite und wichtigere Frage: hat sich grad erst mal zurückgestellt.
und @Hyperion: Elixir ist also eine Abstraktionsschicht, die SQLAlchemy abstrahiert, also doppelt abstrakt oder wie ?
edit: Ja, genau, da materialisierte sich die zweite Frage auch schon wieder:
Die Wohnungen sollen eigentlich als Attribut eine Liste aller Mieter (oder deren id, wäre egal), die dort jemals gewohnt haben, haben, kombiniert mit Einzugs- und Auszugsdatum. Jetzt kann ich aber keine Liste mehr als Attirbut benutzen, oder ?
Soweit hab ich die Arbeitsweise auch grob verstanden.
Erstes Problem: Laut Tutorial kann man ja die deklarative Methode benutzen, um die entsprechende Tabelle für das jeweilige Objekt anzulegen. Das versteh ich da so, daß ich mir diese anfängliche Schreiberei von Zeile 10 bis 24 eigentlich sparen kann, kommt ja alles nochmal in der Klasse. Geht bei mir nur irgendwie nicht, wenn das da nicht steht, legt der Kollege keine Tabellen an.
Zweite und wichtigere Frage: hat sich grad erst mal zurückgestellt.
und @Hyperion: Elixir ist also eine Abstraktionsschicht, die SQLAlchemy abstrahiert, also doppelt abstrakt oder wie ?
edit: Ja, genau, da materialisierte sich die zweite Frage auch schon wieder:
Die Wohnungen sollen eigentlich als Attribut eine Liste aller Mieter (oder deren id, wäre egal), die dort jemals gewohnt haben, haben, kombiniert mit Einzugs- und Auszugsdatum. Jetzt kann ich aber keine Liste mehr als Attirbut benutzen, oder ?
Elixir sollte sich eigentlich mit <http://www.sqlalchemy.org/docs/05/refer ... ative.html> erledigt haben. Da ich aber Djangos ORM einfacher finde, hier mal das Beispiel:
Stefan
Code: Alles auswählen
class Home(models.Model):
street = models.CharField()
city = models.CharField()
class Flat(models.Model):
square_meters = models.IntegerField()
home = models.ForeignKey(Home, related_name="flats")
class Tenant(models.Model):
name = models.CharField()
current_flat = models.ForeignKey(Flat, related_name="tenants")
das liest sich schon ein wenig einfacher, als das, was ich hier grad am produzieren bin. Jetzt bringt mich doch nicht völlig durcheinander.
Kann ich denn mit diesem Django ORM auch das realisieren:
Eine Liste mit Listen aller Mieter, die schonmal in der Wohnung gewohnt haben in der Form (Mieterobjekt, Einzugsdatum, Auszugsdatum), die dann als Attribut der Wohnung geführt wird ?
Kann ich denn mit diesem Django ORM auch das realisieren:
Eine Liste mit Listen aller Mieter, die schonmal in der Wohnung gewohnt haben in der Form (Mieterobjekt, Einzugsdatum, Auszugsdatum), die dann als Attribut der Wohnung geführt wird ?
Würde ich mit einem "Mietverhältnis" modellieren:
Liste aller Mieter einer Wohnung:
Es müsste noch einen effizienteren Weg geben, an den Namen des Mieters zu kommen, irgendwas mit `select_related`, doch ich bin zu faul zum Nachgucken.
Stefan
Code: Alles auswählen
class Tenancy(models.Model):
moved_in = models.DateField()
moved_out = models.DateField()
tenant = models.ForeignKey(Tenant, related_name="tenancies")
flat = models.ForeignKey(Flat, related_name="tenancies")
Code: Alles auswählen
class Flat...
def all_tenants(self):
return [(t.tenant.name, t.moved_in, t.moved_out)
for t in self.tenancies.order_by('moved_in')]
Stefan
ah ok, ich war da so in ähnlicher Richtung unterwegs:, wobei deine Bezeichnung "Mietverhältnis" mir grad mal klargemacht hat, was ich da eigentlich selber mit meine. Nur bei mir wird nur die MieterID gespeichert. Versteh ich das richtig, daß also so eine Art Zeiger auf diesen speziellen Mieter ist ? Wär ja eigentlich dann so, wie es meinem Verständnis nach sein sollte.
Code: Alles auswählen
class FlatsTenantHistory(Base):
__tablename__ = 'flats_tenant_history'
id = Column(Integer, primary_key=True)
tenant_id = Column(Integer, nullable=False)
date_of_move_in = Column(String)
flat_id = Column(Integer, ForeignKey('flats.id'))
tenant = relation(Flat, backref=backref('flats_tenant_history',
order_by=id))
def __init__(self, tenant_id, date_of_move_in):
self.tenant_id = tenant_id
self.date_of_move_in = date_of_move_in
Code: Alles auswählen
tenant = models.ForeignKey(Tenant, related_name="tenancies")
tenant referenziert für ein spezielles Exemplar dieser Klasse zu einem anderen Objekt derjenigen Klasse, die du im ForeignKey angibst, hier als Tenant. tenancies ist dann der Name einer Art Menge, die alle FlatsTenantHistory Objekte welche wie grade beschrieben in Beziehung zu Tenant stehen beinhaltet.
Der "related_name" bei Django ist die Rückrichtung der 1:N Assoziation, d.h. zu einem Mietverhältnis gehört eine Wohnung, wie man über "flat" erreicht und von der Wohnung aus kommt man mit "tenancies" zu alle Mietverhältnissen für diese Wohnung.
Stefan
Stefan
So, da hab ich jetzt zumindest grundlegend dieses SA verstanden und wollte hier mal fragen, ob mein Code denn in der Form ausbaufähig ist, oder eher einer Komplettüberarbeitung bedarf: http://paste.pocoo.org/show/134848/
(es geht immer noch um die Miethausverwaltung)
Schönen Gruß, Stephan
(es geht immer noch um die Miethausverwaltung)
Schönen Gruß, Stephan