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

Antworten:


163

In Ihrer Modelldefinition:

import os

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

    def filename(self):
        return os.path.basename(self.file.name)

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 %}

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

Durch den Zugriff wird obj.file.nameder gesamte Pfad im Medienverzeichnis zurückgegeben, z. B. tasks/132/foo.jpgund nicht foo.jpg.
Shacker
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.