Daten aus zwei Klassen in ein template

Django, Flask, Bottle, WSGI, CGI…
BlackJack

@django-yip: Das Beispiel ist nicht falsch weil `Bar` hier die `Model`-Klasse ist. Die Definition wird nicht gezeigt, aber ja bei der Defintion vom Klassenattribut `Foo.bar` benutzt, also sollte man davon ausgehen dass es existiert also irgendwo davor importiert wird oder ein ``class Bar(Model): …`` weiter oben steht.

Du solltest Dir vielleicht auch mal angewöhnen der Namenskonvention zu folgen das man Klassennamen in MixedCase statt in kleinbuchstaben schreibt.

Man kann nicht einfach so auf Namen zugreifen die in anderen Namensräumen definiert sind. Es könnte ja auch mehrere Klassen mit einem `bar`-Attribut geben, welches sollte denn da dann genommen werden? Auf magische Weise das welches man haben möchte? ;-)

Selbst wenn man das könnte, welcher Wert wäre denn dann `mobilfunknummer`? Also welche Mobilfunknummer ganz konkret? Und da Du alles klein schreibst gibt es denn auch eine `Model`-Klasse mit dem Namen? Warum ist die nicht definiert? Denn dann ginge ja wieder die Zeile die Du da stehen hast. (Ob sie sinnvoll ist hängt dann noch mal davon ab was dort eigentlich gemacht werden soll.)
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Code: Alles auswählen

 mobilfunknummer = mobilfunknummer.objects.get(pk=1)
Das wird wohl dann der Fehler sein, da bei mir mobilfunknummer einmal ForeignKey ist einmal eine Model Klasse ist. Werde mal versuchen dies so umzuändern, dass Model-Klassen immer mit groß Buchstaben beginnen.
BlackJack

@django-yip: Das ist zwar nicht gut wenn die Klassen nicht den Namenskonventionen entsprechen, aber wenn es die Klasse mit dem Namen gibt, müsstest Du halt den lokalen Namen anders nennen damit der lokale Name nicht die Klasse überdeckt. Dass das Klassenattribut irgendwo auch so heisst ist egal. Das ist ein anderer Namensraum.

Und es gilt natürlich das was Sirius3 über die Sinnhaftigkeit des Codes und den unbenutzen Argumenten gesagt hat.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Sirius3 hat geschrieben:Was ist modeladmin und queryset?
So steht es in der Doku -> https://docs.djangoproject.com/en/1.7/r ... n/actions/

Hab mir nur daran gehalten. Und es funktioniert ja auch, bloß Werte aus einer zweiten DB zu erhalten noch nicht.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@django-yip:
Die Admin-Klassen sind eine Abstraktion von Django, welche die generische Darstellung von Modeldaten unter Beachtung von Benutzerrechten ermöglichen. Das ist zunächst eine tolle Vereinfachung und macht es möglich, schnell Modeldaten zur Anzeige und in Formularen zur Änderung anzubieten. So generiert Django den Adminbereich. Der Hund liegt dort begraben, wo man mit den Adminklassen mehr machen will, als der Standardweg vorsieht - die APIs sind z.T. undokumentiert und man verlässt die klassische View-Template-Trennung, welche Django fürs Programmieren von Webseiten vorsieht. Du musst hier sehr genau wissen, was Du erreichen willst, z.B. ist die Erweiterung eines AdminForms mit Standard-Subformularen gut möglich (sogenannte Inlineformulare), spezielle Anforderungen aber mitunter sehr schwierig über die Adminklassen zu implementieren. Im Zweifelsfalle ist die Lösung, einen eigenen benutzerdefinierten View zu erstellen, einfacher als die Integration über die Adminklassen. Diesen Hinweis findest Du auch in der Doku.
django-yip hat geschrieben:Und es funktioniert ja auch, bloß Werte aus einer zweiten DB zu erhalten noch nicht.
Du meinst sicherlich ein zweites Model und nicht DB, eine zweite DB wäre eine andere Datenbankverbindung.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

jerch hat geschrieben:Du meinst sicherlich ein zweites Model und nicht DB, eine zweite DB wäre eine andere Datenbankverbindung.
Richtig, sorry.

Das bedeutet ohne ne neue view zu bauen, ist es nicht so einfach möglich?! Dann brauch ich da nicht weiter Zeit zu investieren.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@django-yip:
Ob das, was Du vorhast, einfach mit den Adminklassen umsetzbar ist, kann ich nicht beantworten, da ich nicht weiss, was Du alles drin haben möchtest. Beschreib doch mal mit Worten, was da passieren soll.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

jerch hat geschrieben:@django-yip:
Ob das, was Du vorhast, einfach mit den Adminklassen umsetzbar ist, kann ich nicht beantworten, da ich nicht weiss, was Du alles drin haben möchtest. Beschreib doch mal mit Worten, was da passieren soll.
Ich dachte es wäre mit meinem ersten Post deutlich gewesen. Aber ich versuche es nochmal.

Ich bekomme die Daten vom Modell "Sim" per action Auswahl im Adminbereich.

Bild

Damit bekomme ich die Daten:

- Mobilfunknummer:
- Kartennummer:
- Pin:

Und das funktioniert per "entries = queryset"

Nun möchte ich aber auch vom Modell "Grundtarife" zur passenden mobilfunknummer den grundtarif haben. Damit ich am Ende in der HTML Ausgabe die Werte:

- Mobilfunknummer:
- Kartennummer:
- Pin:
- Grundtarif:

Verständlich so?
BlackJack

@django-yip: Und was für einen Datentyp haben die Objekte aus dem `queryset`? `sim`? Dann musst Du doch eigentlich nur in Deinem Modell schauen über welche Attribute man dort heran kommt. Von den Modellen die Du gezeigt hast kann man sagen das Du von dem `sim`-Objekt an den Vertrag und von dort an den Grundtarif kommen kannst.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

BlackJack hat geschrieben:@django-yip: Und was für einen Datentyp
text/html

BlackJack hat geschrieben: Von den Modellen die Du gezeigt hast kann man sagen das Du von dem `sim`-Objekt an den Vertrag und von dort an den Grundtarif kommen kannst.

Hab ich das nicht versucht? Finde aber keine Lösung wie man da rankommt.
BlackJack

@django-yip: Die Objekte aus dem `queryset` haben ganz sicher nicht den Datentyp „text/html”. Das kann ja nicht einmal ein Datentyp in Python sein, denn ein '/' kann nicht in einem Namen vorkommen. Datentyp und Klasse sind in Python synonyme Begriffe. Der Datentyp legt fest welche Attribute, Methoden, und welches Verhalten ein Objekt hat. Wenn man also etwas mit Objekten in Python anstellen möchte, dann muss man wissen welchen Typ die haben, denn sonst weiss man ja gar nicht *was* man mit den Objekten tun kann.

Insofern hast Du nicht wirklich versucht an die gewünschten Informationen zu kommen, denn einfach wild herumraten ist kein zielführender, ernsthafter Versuch eine Lösung zu finden. Du musst da schon etwas methodischer Vorgehen und Deine Lösung Schritt für Schritt mit den gegebenen Mitteln und Informationen aufbauen und am besten auch jeden Schritt überprüfen, ob da jeweils das von Dir erwartete Teilergebnis heraus kommt, sowohl was die Datentypen als auch die Werte betrifft.

Ausgangspunkt sind die Argumente welche die Funktion bekommt, der Datenbankinhalt, Deine Modelldefinitionen, und die Django-API. Wenn Du also in einer Lösung `queryset` nicht verwendest, dann sieht das schon mal sehr komisch aus. Oder Du müsstest noch mal genau definieren was bei der Aktion eigentlich passieren soll. Denn das die Auswahl des Benutzers nicht berücksichtigt wird, erscheint erst einmal merkwürdig/unerwartet.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Ich weiß ganz ehrlich nicht was du von mir willst?! :K

Ich hab doch alles gepostet (code sowie was ich haben möchte), was relevant ist und daraus müsstest du - als langjähriger python Entwickler - doch an die Info kommen welcher Datentyp?! Ist ja nicht so das ich irgendein code verstecke.

Also entweder ist man behiflich oder man lässt es sein. MIch hier bloss zu stellen ist ja nicht notwendig, da ich ja schon bereits geschrieben hatte dass ich mich gerade mit django beschäftige und total Neuling bin.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

django-yip hat geschrieben:Ich hab doch alles gepostet (code sowie was ich haben möchte), was relevant ist und daraus müsstest du - als langjähriger python Entwickler - doch an die Info kommen welcher Datentyp?! Ist ja nicht so das ich irgendein code verstecke.
Nee, du hast Code gezeigt von dem du glaubst, dass er relevant ist. Da ist ja noch viel mehr Code, welcher ebenfalls wichtig ist (Komm jetzt aber nicht auf die Idee dein ganzes Projekt hier zu posten, so viel Zeit zum Lesen hat keiner ;-) ). Irgendwo stecken da sicher auch die Typen drin, aber welche das sind, das kann keiner von uns wissen. Deinem Code sieht man das nicht an, wir sind ja alles keine Hellseher. Und die wenigen Hellseher die sich hier rumtreiben, bei denen ist meistens die Glaskugel defekt.
django-yip hat geschrieben:Also entweder ist man behiflich oder man lässt es sein. MIch hier bloss zu stellen ist ja nicht notwendig, da ich ja schon bereits geschrieben hatte dass ich mich gerade mit django beschäftige und total Neuling bin.
BlackJack hat dich nicht bloßgestellt. Er hat lediglich geschrieben, dass du dich mit der Materie beschäftigen sollst. Das du behauptest, dass der Typ "text/html" sei zeigt ganz deutlich, dass du dir nicht wenigstens mal die Mühe gemacht hast den Code zu starten und dir einfach den Typ hast ausgeben lassen. Was willst du denn da für Hilfe erwarten, wenn du selbst nichts beiträgst? Falls du es nicht schaffen solltest an die Typinformation heran zu gelangen, dann solltest du vielleicht zunächst ein Python-Tutorial vernünftig durcharbeiten. Sonst ist Django nämlich ein paar Nummern zu groß für dich.
Das Leben ist wie ein Tennisball.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Ich weiß ja auch nicht was du meinst mit "code gestarten" ?

Aber ich habe mal Wikipedia dazu befragt. Also wollt Ihr wissen wie die Daten in der DB gespeichert werden? ForeignKey per int und die charfiels per varchar. Allerdings wäre mir nicht bewusst, dass ich das irgendwo eingestellt habe, wie er was zu speichern hat.
BlackJack

@django-yip: Mit „code gestartet” ist gemeint Du solltest mal *Dein* Programm laufen lassen nachdem Du es entsprechend geändert hast das Dir die Datentypen zu den Objekten ausgegeben werden. Zum Beispiel zu `queryset`.

Ich (denke) ich weiss welche Datentypen Du da hast und ich kann nachlesen was man damit machen kann. Das kannst *Du* aber auch. Deine Modelle kenne ich aber nicht, erstens nicht alle Definitionen und zweitens nicht die Semantik und was die einzelnen Modelle und Attribute bedeuten. Da kann man nur raten. Und das ging ja auch schon schief, zum Beispiel wenn man die Annahme trifft das zu einer SIM nur eine Mobilfunknummer gehören kann, da hast Du ja schon widersprochen.

Ich vermute mal das `queryset`-Objekt, welches den Datentyp `QuerySet` hat, fragt `sim`-Exemplare ab. Das habe ich jetzt mal aus der HTML-Überschrift von dem Bildschirmfoto des Adminbereichs abgeleitet. Den Code dazu hast Du nicht gezeigt. So viel zum Code verstecken. Die Definitionen der Modelle enthalten „...” und das Modell `mobilfunknummer` hast Du auch nicht gezeigt. Also kann man hier auch nur Vermutungen anstellen wie das aussehen mag. Das `vertrag.grundtarif` ein Fremdschlüssel in `grundtarife` ist und dieses Modell/diese Tabelle dann ein Attribut/eine Spalte `grundtarif` hat, sieht etwas eigenartig aus.

Mal angenommen das `queryset` fragt tatsächlich `sim`-Exemplare ab, dann kann man von jedem einzelnen durch einfachen Attributzugriff das dazugehörige `mobilfunknummer`-Exemplar abfragen. Wie der Datentyp davon aussieht wissen wir nicht — hast Du nicht gezeigt. Da kann man also nur indirekt etwas drüber sagen, nämlich weil wir durch die Definition von `vertrag`-Modell wissen das `mobilfunknummer`-Exemplare ein `vertrag_set`-Attribut haben müssen, was ein `QuerySet`-Exemplar ist. Man kann darüber also an die Verträge (Mehrzahl!) zu der `mobilfunknummer` kommen. Hier stellt sich jetzt die Frage wieviele Verträge es geben kann für eine `mobilfunknummer`. Wenn es mehr als einen geben kann, dann kann es ja auch mehr als einen zur SIM geben. Falls es nur einen geben kann ist `vertrag.mobilfunknummer` vielleicht etwas zu ”grosszügig” definiert und man wollte da kein `ForeignKey` sondern ein `OneToOne` Feld definieren. Wenn man dann das oder die `vertrag`-Exemplare hat, kann man dort ganz einfach den Grundtarif als Attribut abfragen.

Unter der Voraussetzung das es zu jeder Mobilfunknummer genau einen Vertrag gibt, könnte das ausgeben aller Grundtarife zu den ausgewählten SIMs so aussehen (ungetestet):

Code: Alles auswählen

for sim in queryset:
    print sim.mobilfunknummer.vertrag_set.get().grundtarif.grundtarif
Hier sieht man vielleicht auch warum ich `grundtarif` als Attribut/Feld von `grundtarife` komisch finde. Kann es sein dass dieses Feld/die Spalte vielleicht besser `name` oder `beschreibung` heissen sollte?
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Ich habe mittlerweile Models mit Großbuchstaben gemacht, damit keine Verwirrung kommt.

Aber zum Verständnis:

for Sim(Model) in queryset:
print Sim(Model).mobilfunknummer(ForeignKey-in-Model-Sim).Vertrag(Model)_set.get().grundtarif(attribut).grundtarif(attribut)

?

Wenn es so wie oben gemeint ist, bekomme ich die Fehlermeldung:
Exception Type: AttributeError
Exception Value:

'Mobilfunknummer' object has no attribute 'Vertrag_set'
BlackJack

@django-yip: Da sollte im ganzen Ausdruck kein einziges `Model` vorkommen, also alles kleingeschrieben werden. Das `Sim`-Modell gibt es ja nur *einmal*, die Schleife muss also über Exemplare davon gehen und nicht über den Datentyp.

Das Du die Erklärung zu den einzelnen Teilausdrücken wie Funktionsaufrufe schreibst ist sehr verwirrend.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Wunderbar! Mit alles klein schreiben tut sich was :)

Jetzt schreibt er mir den grundtarif in die Console. Kannst mir evtl. noch sagen wie ich das ins template bekomme?
BlackJack

@django-yip: Erstelle eine Datenstruktur mit den gewünschten Informationen, beispielsweise eine Liste mit Tupeln mit den entsprechenden Werten pro SIM, übergibt die an die `render_to_response()`-Funktion und schreib im Template entsprechenden Template-Code der die Daten dann ins HTML einbaut.
django-yip
User
Beiträge: 31
Registriert: Montag 19. Januar 2015, 11:12

Danke! Klappt wunderbar!
Antworten