2009-07-27 13 views
121

Ich versuche, meine Uploads einzurichten, so dass, wenn Benutzer Joe eine Datei hochlädt, es zu MEDIA_ROOT/Joe geht, anstatt alle Dateien zu MEDIA_ROOT gehen zu lassen. Das Problem ist, ich weiß nicht, wie ich das im Modell definieren soll. So sieht es derzeit aus:Django FileField mit upload_to zur Laufzeit

class Content(models.Model): 
    name = models.CharField(max_length=200) 
    user = models.ForeignKey(User) 
    file = models.FileField(upload_to='.') 

Also was ich will ist statt '.' Als upload_to muss es der Name des Benutzers sein.

Ich verstehe, dass ab Django 1.0 Sie Ihre eigene Funktion definieren können, um die upload_to zu handhaben, aber diese Funktion hat keine Ahnung, wer der Benutzer sein wird, also bin ich ein bisschen verloren.

Danke für die Hilfe!

Antwort

242

Sie wahrscheinlich the documentation gelesen haben, also hier ist ein einfaches Beispiel, um es sinnvoll machen:

def content_file_name(instance, filename): 
    return '/'.join(['content', instance.user.username, filename]) 

class Content(models.Model): 
    name = models.CharField(max_length=200) 
    user = models.ForeignKey(User) 
    file = models.FileField(upload_to=content_file_name) 

Wie Sie sehen können, brauchen Sie nicht einmal die Dateinamen gegeben verwenden - Sie außer Kraft setzen könnten, dass in Ihrem upload_to auch aufrufbar, wenn Sie möchten.

+0

Ja, es gehört wahrscheinlich in die Dokumentation - es ist eine vernünftige FAQ auf IRC – SmileyChris

+2

Funktioniert das mit ModelForm? Ich kann sehen, dass diese Instanz alle Attribute des Klassenmodells hat, aber es gibt keine Werte (nur eine Str des Feldnamens). In der Vorlage ist der Benutzer ausgeblendet. Ich muss vielleicht eine Frage einreichen, ich habe das stundenlang gegoogelt. – mgag

+0

Ja, es funktioniert, und ja, Sie sollten eine neue Frage stellen (oder um Hilfe auf #django irc bitten) – SmileyChris

11

Das hat wirklich geholfen. Für ein bisschen mehr Kürze halber entschied Lambda in meinem Fall zu verwenden:

file = models.FileField(
    upload_to=lambda instance, filename: '/'.join(['mymodel', str(instance.pk), filename]), 
) 
+2

Dies funktionierte bei mir in Django 1.7 nicht mit Migrationen.Es wurde stattdessen eine Funktion erstellt und die Migration ausgeführt. – aboutaaron

+0

Auch wenn Sie Lambda nicht mit dem str (instance.pk) arbeiten können, ist es eine gute Idee, wenn Sie Probleme mit dem Überschreiben von Dateien haben, wenn Sie nicht wollen. –

+0

Instanz hat vor dem Speichern kein 'pk'. Es funktioniert nur für Updates, nicht für Kreationen (Inserts). –

3

Ein Hinweis zur Verwendung des ‚instance‘ pk Wertes des Objekts. Gemäß der Dokumentation:

In den meisten Fällen wurde dieses Objekt noch nicht in der Datenbank gespeichert. Wenn es das Standard-AutoField verwendet, hat es möglicherweise noch keinen Wert für sein Primärschlüsselfeld.

Daher hängt die Gültigkeit der Verwendung von PK davon ab, wie Ihr bestimmtes Modell definiert ist.

+0

Ich habe None als Wert erhalten. Ich kann nicht herausfinden, wie ich es beheben kann. Kannst du das etwas genauer erklären? –

Verwandte Themen