Elixir die dritte: Objekt statt Werteliste als Rückgabe

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hi, jetzt stehe ich vor einem Problem, dass ich bisher nicht lösen konnte. Im Tutorial sieht man als Rückgabewerte immer richtige Werte. Z.B.

Code: Alles auswählen

>>> Movie.query.all()
[<Movie "Blade Runner" (1982)>]
Wenn ich das hier eins zu eins nachvollziehe bekomme ich immer ein Objekt

Code: Alles auswählen

>>> Movie.query.all()
[<model2.Movie object at 0x17a3850>]
Deshalb funktionieren bei mir Abfragen auch nicht
sqlalchemy.exc.InvalidRequestError: 'has()' not implemented for collections. Use any().
Warum ist das so? Ich komme hier definitiv nicht weiter.
lunar

Die Rückgabe beider Beispiele ist identisch. Beide Beispiele zeigen eine Liste mit einem Objekt, welches anscheinend von Typ "Movie" ist. Der einzige Unterschied besteht darin, dass "Movie" aus dem ersten Beispiel __repr__ implementiert, während beim zweiten Beispiel die "Standardimplementierung" zum Tragen kommt.

Vgl:

Code: Alles auswählen

class Movie(object):
    def __init__(self, name, year):
         self.name = name
         self.year = year

print([Movie('Blade Runner', 1984)])
und:

Code: Alles auswählen

class Movie(object):
    def __init__(self, name, year):
         self.name = name
         self.year = year

    def __repr__(self):
        return '<{0} "{1.name}" ({1.year})>'.format(self.__class__.__name__, self)

print([Movie('Blade Runner', 1984)])
Das sollte man als Python-Entwickler aber wissen.

Warum "has()" nicht funktioniert, kann ich Dir nicht sagen. Mit dem Unterschied zwischen den Beispielen hat das aber schlicht gar nichts zu tun. Die Fehlermeldung lässt darauf schließen, dass "has()" für Listen nicht implementiert ist. Warum, dass sagt dir die Dokumentation von Elixir.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hi lunar, danke für die Antwort. Ich habe gerade festgestellt, dass ich mich vertippt habe. Ich habe nur __rep__(self) eingegeben (peinlich, peinlich) :oops:

Allerdings ändert das nix an dem Problem, dass ich die Abfragen nicht hinbekomme, dabei ist es eine "simple" OneToMany

Das sind die beiden Tabellen.

Code: Alles auswählen

class MaterialGroups(Entity):
    using_options(shortnames=True)
    
    shortcut = Field(Unicode(5), primary_key=True)
    parent = Field(Unicode(5))
    name = OneToMany('MaterialGroupName')

class MaterialGroupName(Entity):
    using_options(shortnames=True)

    name=Field(Unicode(20))
    mg = ManyToOne('MaterialGroups')
    language = ManyToOne('Languages')
Ich möchte jetzt eine Abfrage machen, in der ich sämtliche Namen der Warengruppe erhalte, die als Sprache "de" haben. Mein Versuch

Code: Alles auswählen

MaterialGroups.query.filter(MaterialGroups.name.has(language=u"de")).all()
funktioniert wegen besagter Fehlermeldung nicht. Ich sehe aber keinen Unterschied zwischen meinem Programm und dem Tutorial
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Du verwendest OneToMany, das Tutorial ManyToOne. Die Fehlermeldung erklärt dir, wie du weiter zu verfahren hast.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Darii hat geschrieben:Du verwendest OneToMany, das Tutorial ManyToOne. Die Fehlermeldung erklärt dir, wie du weiter zu verfahren hast.
Das hilft leider nicht. .any() liefert auch nicht das gewünschte Ergebnis.

Code: Alles auswählen

class Languages(Entity):
    using_options(shortnames=True)

    name = Field(Unicode(15))
    shortcut = Field(Unicode(2), primary_key=True)
    mgname = OneToMany('MaterialGroupName')

    def __repr__(self):
        return '<Languages name:"%s" (%s) >' % (self.name, self.shortcut)

class MaterialGroups(Entity):
    using_options(shortnames=True)
    
    shortcut = Field(Unicode(5), primary_key=True)
    parent = Field(Unicode(5))
    name = OneToMany('MaterialGroupName')
    

    def __repr__(self):
        return '<MaterialGroups shortcut:"%s" parent:"%s" name:%s>' % (self.shortcut, self.parent, self.name)

class MaterialGroupName(Entity):
    using_options(shortnames=True)

    name=Field(Unicode(20))
    mg = ManyToOne('MaterialGroups')
    language = ManyToOne('Languages')

    def __repr__(self):
        return '<MaterialGroupName "%s" (%s)>' % (self.name, self.language)
Das sind die drei Klassen, um die es geht. Der Befehl

Code: Alles auswählen

print MaterialGroups.query.filter_by(parent=u"root").all()
liefert diese Ausgabe

Code: Alles auswählen

[
    <MaterialGroups shortcut:"uc" parent:"root" name:
        [
            <MaterialGroupName "Mikrocontroller" (<Languages name:"Deutsch" (de) >)>, 
            <MaterialGroupName "Microcontroller" (<Languages name:"Englisch" (en) >)>
        ]
    >, 
    <MaterialGroups shortcut:"semi" parent:"root" name:
        [
            <MaterialGroupName "Halbleiter" (<Languages name:"Deutsch" (de) >)>, 
            <MaterialGroupName "Semiconductor" (<Languages name:"Englisch" (en) >)>
        ]
    >, 
    <MaterialGroups shortcut:"pass" parent:"root" name:
        [
            <MaterialGroupName "Passive Bauteile" (<Languages name:"Deutsch" (de) >)>, 
            <MaterialGroupName "Passive Components" (<Languages name:"Englisch" (en) >)>
        ]
    >
]
Ich habe es von Hand formatiert, damit es deutlicher wird. Was ich jetzt möchte sind die DEUTSCHEN Namen aller Warengruppen, die parent="root" haben. Wie man sieht enthält der Materialgruppen-Name eine weitere Liste mit allen vorhandenen Namen.

Code: Alles auswählen

    test= MaterialGroups.query.filter_by(parent=u"root").all()
    for i in test:
        for j in i.name:
            print j.language.shortcut
Ich kann mich jetzt durch die Listen "durchhangeln" um an die gewünschte Information zu kommen, aber das ist ja nicht Sinn von SQL. Ich möchte bereits die Abfrage so gestalten, dass ich NUR eine Liste der gewünschten Namen zurückerhalte. Aber hier scheitere ich bisher. Vielleicht kann mir jemand einen Schubs geben, der mich ein Stück weiter bringt
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

burli hat geschrieben:Das hilft leider nicht. .any() liefert auch nicht das gewünschte Ergebnis.
Was tut es denn? Wenn du nicht erzählst was du willst kann man dir nicht helfen, das mit "parent" war mir z.B. neu. any() ist das was du haben möchtest. Filter kann man übrigens kaskadieren, also Class.query.filter(...).filter(...).all()
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich habe noch keinen Weg gefunden zu erreichen, was ich eigentlich wollte. Aber ich komme auf Umwegen da hin. Ich mach erstmal weiter, vielleicht finde ich noch was.

Immerhin verstehe ich langsam aber sicher mehr von dem, wie es funktioniert. Ich kämpfe einfach weiter
Antworten