Unterschied save() <-> save_model()

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Hallo,

ich in nächster Zeit in meinen Arbeiten die Models um einige Funktionen erweitern möchte, habe ich hierzu ein paar grundsätzliche Fragen.



http://docs.djangoproject.com/en/dev/to ... el-methods

Code: Alles auswählen

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, force_insert=False, force_update=False):
        do_something()
        super(Blog, self).save(force_insert, force_update) # Call the "real" save() method.
        do_something_else()

Verstehe ich es richtig, dass hier die vordefinierte save-Methode überschrieben wird, aber in dieser Methode, die überschreibt, dann die vordefinierte save-Methode aufgerufen wird?



http://docs.djangoproject.com/en/dev/re ... orm-change

Code: Alles auswählen

class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        obj.save()
Welche save-Methode wird hier mit dem obj.save() genau aufgerufen?
Die gleiche wie im Beispiel oben, nein oder!?



----------------------------------------------------------

Worin besteht der Unterschied zwischen diesen beiden Funktionen (save() <-> save_model())?

Es wird jeweils die Methode der übergeordneten Klasse überschrieben wenn ich das richtig verstehe. Aber in beiden kann man doch Sachen zur Speicherung der Daten modifizieren.

Ich freue mich auf lehrreiche Rückmeldung. Ich könnte sicherlich auch einfach experimentieren und es würde funktionieren. Aber bevor ich damit anfange hätte ich einfach gerne ein wenig Hintergrundwissen.

-------------------------------------------------------------

Noch eine andere Geschichte:
Ich würde gerne in meinem CMS immer einen Wert vorbelegen mit default. Dies soll aber kein String sein, sondern ein durch eine Funktion errechneter Wert sein. Wie realisiere ich das? Ist so etwas wie default="funktionsaufruf" möglich???
Habe es versucht, aber hat nicht ganz geklappt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Verstehe ich es richtig, dass hier die vordefinierte save-Methode überschrieben wird, aber in dieser Methode, die überschreibt, dann die vordefinierte save-Methode aufgerufen wird?
Ja, ist ja auch recht Eindeutig, der Code.
ferix hat geschrieben:Welche save-Methode wird hier mit dem obj.save() genau aufgerufen?
Die gleiche wie im Beispiel oben, nein oder!?
Wenn die ArticleAdmin-Klasse an deine Blog-Klasse gebunden ist und du ``Blog`` im Admin editierst, dann ja.
ferix hat geschrieben:Worin besteht der Unterschied zwischen diesen beiden Funktionen (save() <-> save_model())?
``save()`` wird immer ausgeführt wenn Daten in der Datenbank geändert werden sollen, ``save_model`` hingegen, wird nur aufgerufen wenn du im Admin eine Instanz abspeicherst und ruft dann meist ihrerseits ``save()`` auf.
ferix hat geschrieben:Aber in beiden kann man doch Sachen zur Speicherung der Daten modifizieren.
Richtig, der Unterschied ist nur wo man wie auf das Speichern reagieren will.
ferix hat geschrieben:Noch eine andere Geschichte:
Ich würde gerne in meinem CMS immer einen Wert vorbelegen mit default. Dies soll aber kein String sein, sondern ein durch eine Funktion errechneter Wert sein. Wie realisiere ich das? Ist so etwas wie default="funktionsaufruf" möglich???
Habe es versucht, aber hat nicht ganz geklappt.
Ich würde einfach bevor das Formular an den Browser geschickt wird, diesen Wert errechnen und einsetzen. Habe erst gestern wieder einiges an den Forms gehackt und finde sie immer noch etwas zu unflexibel.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Statt `save()` zu überschreiben, sollte man lieber Signale benutzen. Das ist sauberer.

Stefan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

sma hat geschrieben:Statt `save()` zu überschreiben, sollte man lieber Signale benutzen. Das ist sauberer.
Naja, es ist schon manchmal praktisch ``save()`` zu überschreiben, zum Beispiel wenn man Felder beim anlegen mit einem berechneten Wert befüllen will. Außerdem fand ich es immer schnön integriert, dass das Objekt sich selbt speicherfertig macht.

Ich weiß nicht ob das immer noch so ist, aber wenn ``post_save()`` aufgerufen wird, sind die Werte in einem ManyToMany-Feld noch nicht aktualisiert, somit bekommt man eigentlch ein Objekt was noch nicht "fertig" ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Leonidas hat geschrieben: Ich würde einfach bevor das Formular an den Browser geschickt wird, diesen Wert errechnen und einsetzen. Habe erst gestern wieder einiges an den Forms gehackt und finde sie immer noch etwas zu unflexibel.
Das Problem bei der Sache ist: Der Nutzer soll den erechneten Wert auch vorm Abspeichern bei Bedarf verändern können. Daher möchte ich es gerne über den default lösen.

Gibt es da keine Möglichkeit?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Das Problem bei der Sache ist: Der Nutzer soll den erechneten Wert auch vorm Abspeichern bei Bedarf verändern können. Daher möchte ich es gerne über den default lösen.
Und was hindert ihn, den eingesetzten Wert zu ändern?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Na wenn ich richtig verstehe hast du doch gemeint, dass man den Wert in dem Teil der überschriebenen save-Methode errechnen soll oder?

Dann würde er nicht direkt beim Anlegen eines neuen Datensatzes wo noch alle Felder leer sind angezeigt werden.

Oder habe ich das falsch verstanden? Wie würde es denn noch zu realisieren sein ohne "default"? Wie gesagt wenn ich auf zum Beispiel "Neue Seite hinzufügen" gehe soll der errechnete Wert bereits im Feld stehen und änderbar sein.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Na wenn ich richtig verstehe hast du doch gemeint, dass man den Wert in dem Teil der überschriebenen save-Methode errechnen soll oder?
Ich habe gesagt, bevor es an den Browser geschickt wird, nicht nachdem der User auf "Save" geklickt hat.

Aber ich nehme an, du willst über den Admin einen Standardwert vergeben? Dann kann man es tatsächlich nur über Hacks, soweit ich weiß. Dann würde ich in save_model nachsehen, ob der User das Feld Leergelassen hat und wenn ja, dort dann was einsetzen. Ja, ist hässlich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Hmm ja das wäre echt unschön.

Was hat es denn mit dem Callable Objects, die man bei default verwenden darf auf sich?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Was hat es denn mit dem Callable Objects, die man bei default verwenden darf auf sich?
Hmm, damit könnte es gehen. Die kannte ich noch gar nicht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Und was soll das genau sein bzw. wie soll das funktionieren?

Dachte man kann da irgendwie ganz normal ne Funktion aufrufen, die dann den Wert ausgibt, aber das hat irgendwie nicht so ganz hingehaun.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Und was soll das genau sein bzw. wie soll das funktionieren?

Dachte man kann da irgendwie ganz normal ne Funktion aufrufen
Funktionen kann man immer aufrufen. Das Problem in deinem Fall ist aber, dass die Funktion ja nur einmal, zur Definitionszeit aufgerufen wird und somit ist der Default das, was die Funktion damals zurückgegeben hat. Du musst dort einfach eine Funktion einsetzen, *ohne* sie aufzurufen.

Hmm, wenn ich mit meinem Jinja2-Migration Branch fertig bin, sollte ich das auch umstellen...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Und wie setze ich das syntaktisch um?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Und wie setze ich das syntaktisch um?
So wie man das eben in Python macht?

Code: Alles auswählen

def funktion(*args, **kwargs):
    """Tue irgendwas und gebe irgendwas anderes zurück"""

class DeinModel(models.Model):
    name = models.CharField(max_lenght=200, default=funktion)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Ah super funktioniert.
Hatte ich quasi auch von Anfang an so, da ich def funktion(self) gemacht habe, was wohl falsch war!?

Wann verwendet man das denn und wann nicht?

Entschuldigung ich bin in Python noch nicht ganz so fit komme eher aus der XHTML/CSS - Schule :)


Dann habe ich noch eine Frage zu folgendem Beispiel aus der Doku:

Code: Alles auswählen

from django.contrib.localflavor.us.models import USStateField

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is America-centric...

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
            return "Baby boomer"
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        return "Post-boomer"

    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name)
Werden diese definierten Funktionen überhaupt ausgeführt?
Oder müssen die noch spezifisch aufgerufen werden?
Ja oder?
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

ferix hat geschrieben:Ah super funktioniert.
Hatte ich quasi auch von Anfang an so. Hat nur nicht funktioniert, da ich "def funktion(self)" gemacht habe, was wohl falsch war!?

Wann verwendet man das denn und wann nicht?

Entschuldigung ich bin in Python noch nicht ganz so fit komme eher aus der XHTML/CSS - Schule :)


Dann habe ich noch eine Frage zu folgendem Beispiel aus der Doku:

Code: Alles auswählen

from django.contrib.localflavor.us.models import USStateField

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is America-centric...

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
            return "Baby boomer"
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        return "Post-boomer"

    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name)
Werden diese definierten Funktionen überhaupt ausgeführt?
Oder müssen die noch spezifisch aufgerufen werden?
Ja oder?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Ah super funktioniert.
Hatte ich quasi auch von Anfang an so, da ich def funktion(self) gemacht habe, was wohl falsch war!?

Wann verwendet man das denn und wann nicht?
Wenn es eine Methode einer Klasse ist; irgendwie muss man ja auch auf die Klassenattribute zugreifen können.
ferix hat geschrieben:Werden diese definierten Funktionen überhaupt ausgeführt?
Die Methoden werden in dem Beispiel nicht ausgeführt, wozu auch.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten