2014-11-29 3 views
5

Ich habe, was ich als eine einfache Frage sein. In meinem Modell habe ich eine models.ImageField, die so aussieht:Python Django: Wie man eine Datei mit einem Dateinamen auf Instanz pk basierend hochladen

class CMSDocument(BaseItem): 
    thumb = models.ImageField(upload_to= './media/',blank=True) 

Aber ich würde es laden gerne '.media/' + self.pk+ '.png' Ich habe versucht, das Feld innerhalb der Speichermethode des Modells zu aktualisieren, aber das funktioniert nicht, wie der pk nicht bekannt ist, wenn 'save' aufgerufen wird. Ich habe auch versucht, eine benutzerdefinierte Funktion für upload_to hinzuzufügen, wie hier vorgeschlagen: Django: Any way to change "upload_to" property of FileField without resorting to magic?. Aber das lässt das Feld leer. Was kann ich tun?

EDIT: Ich benutze 1.6 Django

EDIT: Ich habe ein post_save Signal, das nicht sehr schön ist:

def video_embed_post_save(sender, instance=False, **kwargs):  
    document = DocumentEmbedType.objects.get(pk=instance.pk)  
    new_thumb = "media/%s.png" % (document.pk,) 
    if not document.thumb == new_thumb: 
     document.thumb = new_thumb 
     document.save() 
    ... 
+0

versuchen diese http://stackoverflow.com/questions/651949/django-access-primary-key-in-models-filefieldupload-to-location – madzohan

+0

Ein sehr hackischer Ansatz besteht darin, in der Save-Methode die ID des letzten Datensatzes zu erhalten und sie dann um eins zu erhöhen und sie als neue ID zu verwenden. – Ymartin

+0

hmmm, ich am Ende tatsächlich ein post_save Signal aufbrauchen, die ein bisschen wie ein Hack ist (ich überprüfen, ob der Dateiname richtig ist schon, wenn ich es nicht ändern und das Modell speichern. Auf diese Weise erhalte ich keine Probleme mit Rekursion). Aber ich werde @madzohan Lösung prüfen. – Magda

Antwort

3

Der Primärschlüssel von der Datenbank zugeordnet ist, so dass Sie bis zu Ihrem Modell warten Zeile wird in der Datenbank gespeichert.

erstens Ihre Daten in zwei Modellen teilen, mit der Miniaturansicht auf dem Kind Modell:

from django.db import models 

from .fields import CMSImageField 


class CMSDocument(models.Model): 
    title = models.CharField(max_length=50) 


class CMSMediaDocument(CMSDocument): 
    thumb = CMSImageField(upload_to='./media/', blank=True) 

Wie Sie verwende ich ein benutzerdefiniertes Feld für das Bild anstelle des Imagefield zu sehen.

So erstellen Sie dann eine fields.py Datei, wo Sie die pre_save Funktion der Klasse von Filefield geerbt Imagefield außer Kraft setzen sollte:

from django.db import models 


class CMSImageField(models.ImageField): 
    def pre_save(self, model_instance, add): 

     file = super(models.FileField, self).pre_save(model_instance, add) 

     if file and not file._committed: 
      # Commit the file to storage prior to saving the model 
      file.save('%s.png' % model_instance.pk, file, save=False) 
     return file 

Da CMSMediaDocument von der CMSDocument Klasse erbt, in dem Moment, pre_save genannt wird wird die progressive PK bereits in der Datenbank gespeichert, so dass Sie die pk von model_instance extrahieren können.

testete ich den Code und sollte gut funktionieren.

Die Admin-Datei im Test verwendet:

from django.contrib import admin 

from .models import CMSMediaDocument 

admin.site.register(CMSMediaDocument) 
Verwandte Themen