Probleme mit Zugriff auf "Inline-Elemente" in safe

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 zusammen,

ich habe ein Model, in dem ich Immobilienobjekte erzeuge.
Dieses hat zusätzlich ein Inline-Model Image, um dem Immobilienobjekt
so viele Bilder wie gewünscht zuordnen zu können.

Jetzt habe ich aber folgendes Problem:
Ich möchte die Bilder, die neu hochgeladen werden von der Größe anpassen.
Doch wie greife ich auf diese zu? Die Variablen des eigenentlichen "Parent" Models
lassen sich ja recht einfach per obj.var aufrufen.
Doch wie greife ich auf Variablen eines Inline-Models innerhalb der save_model
Methode zu?

Hier auch mal mein Code für besseres Verständnis der Sache:

Code: Alles auswählen

class ImageInline(admin.TabularInline):
    model = Image
    extra = 1
    

class PropertyAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

    def save_model(self, request, obj, form, change):
        # Object incl. Bilder speichern
        obj.save()
   
        # Bilder jetzt erst als FileObject abgelegt
        # Fileobject-Methoden/Optionen jetzt möglich
        
        # Hier kommt eine Aktion mit den Bildern
        # ABER WIE ZUGRIFF AUF BILDER???
        
        # Object mit neuen Links zu Bildern speichern
        obj.save
Um ein gerade hochgeladenes Bild zu Bearbeiten muss man das Objekt auch erst einmal speichern oder? Zumindest konnte man vor der Speicherung des Objekts nicht mit FileObject-Methoden auf das Bild zugreifen, da ich dann eine Fehlermeldung mit "MemoryFileCache" irgendwas bekam :)
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Ich hab mal bissel rumprobiert und kann auf die Bilder zugreifen.
Jetzt habe ich nur ein Problem: In dem Moment wo die Bilder angelegt werden
wird der Code in der for schleife wohl irgendwie nicht ausgeführt da passiert nichts.
Erst wenn ich nach dem initialen speichern nochmal speicher würd er ausgeführt.
Jemand ne Idee?
Brauch das unbedingt, da die Bilder ja umgerechnet werden sollen.

Code: Alles auswählen

class ImageInline(admin.TabularInline):
    model = Image
    extra = 1
    

class PropertyAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

    def save_model(self, request, obj, form, change):
        # Object incl. Bilder speichern
        obj.save()
   
        # Bilder jetzt erst als FileObject abgelegt
        # Fileobject-Methoden/Optionen jetzt möglich
        property = Property.objects.get(id=obj.id)
        
        for image in property.images.all():
            print image.title
            print image.image
            print image.image_thumb         
            imagefile = image.image
            print imagefile.width
            print imagefile.path
            os.remove(imagefile.path)
                
        # Hier kommt eine Aktion mit den Bildern
        
        # Object mit neuen Links zu Bildern speichern
        # obj.save
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Du müsstest in dem Form eigentlich ein UploadedFile-Objekt zu fassen haben, welches eine read()-Methode hat. An die Daten eines Form kommst du nach der Validierung über form.cleaned_data[name]. Und ein dein Inline kann ich auch nur in den Quelltext gucken und meine, da gibt es neben save_form und save_model noch eine save_formset-Methode, die du dafür genau überschreiben kannst. Übrigens, ich würde nicht save_model, sondern save_form überschreiben, wenn du da was ändern willst. Bei save_model müsste doch eigentlich schon das Image in "obj" stecken. Das ist dann eigentlich zu spät.

Google findet noch http://code.google.com/p/django-stdimage/, das ich aber nicht kenne. Vielleicht hilft dir ja dieser Google-Service trotzdem :)

Stefan
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

save_model müsste doch eigentlich schon das Image in "obj" stecken.
Genau das tut es komischerweise eben nicht.
Selbst nach obj.save wie im obigen Beispiel tut sich bei dem Upload eines Bildes nichts.
Erst nach einem weiteren Klick auf Speichern greift der Code wie gesagt.
Du müsstest in dem Form eigentlich ein UploadedFile-Objekt zu fassen haben, welches eine read()-Methode hat. An die Daten eines Form kommst du nach der Validierung über form.cleaned_data[name].
Wenn ich in die Doku sehe sind da aber nur Beispiele zur Verwendung in Views und nicht in der Verwendung mit dem Admin und Models oder!?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Use the source, Luke, ähm ferix :)

Das AdminModel macht nichts anderes, als du auch in eigenen Views machen könntest. Es übergibt dir ja das Form-Objekt.

Stefan
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Danke, dass die form übergeben wird, ist mir dann auch aufgefallen :)

Aber worin ist jetzt der Unterschied ob ich print form.cleaned_data['title'] oder print obj.title mache? Gibt beides das gleiche aus und enthält dieselben Daten.
Wann verwendet man was?

Ein save_form habe ich nicht gefunden. Aber was ist genau der Unterschied zwischen save_formset und save_model? Ist in der Doku leider nicht viel zu geschrieben.

Und jetzt zu dem "größten Problem":

Code: Alles auswählen

    def save_model(self, request, obj, form, change):
        # Object incl. Bilder speichern
        obj.save()
   
        # Bilder jetzt erst als FileObject abgelegt
        # Fileobject-Methoden/Optionen jetzt möglich
        print obj.images.all()
Wieso wird bei dem print Befehl erst mit dem 2. Speichern die Bilderliste ausgeben und nicht wie gewünscht beim ersten Mal? Das gibt es doch nicht das müsste doch eigentlich direkt ausgegeben es ist doch mit obj.save vorher gespeichert. Da komme ich nicht mit.

Danke für deine Geduld :)

Christoph
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Habs geschnackelt und alle Fragen erübrigen sich.
Oh man wie gut da kanns morgen weitergehen :)

Achso falls es von Interesse ist erzähle ich nach der Umsetzung gerne mal von meiner Lösung!?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

ferix hat geschrieben:Ein save_form habe ich nicht gefunden.
Möglicherweise ist die neu in Django 1.1 beta. Dort hast du noch kein Objekt, kannst also mit der Form selbst arbeiten, bevor Django das Objekt anlegt, was für einige Dinge möglicherweise zu spät ist.
ferix hat geschrieben: Und jetzt zu dem "größten Problem":

Code: Alles auswählen

    def save_model(self, request, obj, form, change):
        # Object incl. Bilder speichern
        obj.save()
   
        # Bilder jetzt erst als FileObject abgelegt
        # Fileobject-Methoden/Optionen jetzt möglich
        print obj.images.all()
Ich glaube, jetzt verstehe ich. Deine Bild-Objekte haben eine 1:N-Relation zum eigentlichen Objekt. Dieses braucht doch erst einen primary key, der als id automatisch beim Speichern vergeben wird. Nur dann kann man auch die Bildobjekte finden, die auf diesen PK verweisen.

Daher sagte ich ja, verändere die Bilddaten, noch bevor sie überhaupt in die Objekte wandern und wenn wie noch im Formular stecken.

Stefan
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Des Rätsels Lösung war doch save_formet.
Denn diese Methode ist definitiv dazu da da Inline-Model zu speichern.

Ich habe auch herausgefunden, dass zuerst save_model und dann save_formset ausgeführt wird.
Sprich das eigentliche Model ist noch vor den dazugehörigen Inlines gespeichert.

Habe jetzt einfach die save-formset Methode überschrieben, da ich dort
an die Inline-Bilder komme. Bevor die Bilder gespeichert werden, werden
sie bearbeitet, temporör abgelegt und dann gespeichert.

Eine Lösung poste ich noch, wenn die Kommentare etc. passen :)
Antworten