Django FileField: So geben Sie nur den Dateinamen zurück (in der Vorlage)

74

Ich habe ein Feld in meinem Typmodell FileField. Dies gibt mir ein Objekt vom Typ File, das die folgende Methode hat:

File.name: Der Name der Datei einschließlich des relativen Pfads von MEDIA_ROOT.

Was ich will, ist so etwas wie " .filename", das mir nur den Dateinamen und nicht auch den Pfad gibt, so etwas wie:

{% for download in downloads %}
  <div class="download">
    <div class="title">{{download.file.filename}}</div>
  </div>
{% endfor %}

Welches würde so etwas geben myfile.jpg

John
quelle

Antworten:

163

In Ihrer Modelldefinition:

import os

class File(models.Model):
    file = models.FileField()
    ...

    def filename(self):
        return os.path.basename(self.file.name)
Ludwik Trammer
quelle
funktionierte hervorragend, musste aber den Parameter als self.file.name an den Basisnamen übergeben. Ich denke, es braucht dies, da self.file eher ein Dateiobjekt als die Zeichenfolge für die Datei ist.
John
12
Durch das Hinzufügen des @ property-Dekorators wird vermieden, dass file.filename () aufgerufen wird, und es kann einfach file.filename verwendet werden
spedy
1
Überraschenderweise funktioniert diese Lösung sogar mit S3Speicher-Backend.
Stan Redoute
Für mich geht das. Könnten Sie bitte einige Informationen geben, um zu erklären, wie es funktioniert?
xie186
@ user3327344 Mit welchem ​​Teil haben Sie Probleme?
Ludwik Trammer
51

Sie können dies tun, indem Sie einen Vorlagenfilter erstellen:

In myapp/templatetags/filename.py:

import os

from django import template


register = template.Library()

@register.filter
def filename(value):
    return os.path.basename(value.file.name)

Und dann in Ihrer Vorlage:

{% load filename %}

{# ... #}

{% for download in downloads %}
  <div class="download">
      <div class="title">{{download.file|filename}}</div>
  </div>
{% endfor %}
rz.
quelle
Dies ist auch ein schöner Ansatz. Vielleicht etwas tragbarer?
Ben Keating
2
Wie Sie den Filter geschrieben haben, sollte es {{download | filename}} sein
Emil Stenström
4
Vergessen Sie die __init__.pyDatei nicht, um sicherzustellen, dass das Templatetags-Verzeichnis als Python-Paket behandelt wird.
Shuckc
-1

Sie können über das Dateifeldobjekt mit der Eigenschaft name auf den Dateinamen zugreifen.

class CsvJob(Models.model):

    file = models.FileField()

Dann können Sie den Dateinamen des jeweiligen Objekts mit abrufen.

obj = CsvJob.objects.get()
obj.file.name property
DeadDjangoDjoker
quelle
Durch den Zugriff wird obj.file.nameder gesamte Pfad im Medienverzeichnis zurückgegeben, z. B. tasks/132/foo.jpgund nicht foo.jpg.
Shacker