Search code examples
pythondjangofilefilefield

Python Django Template cannot get name from model function


While I understood that I can call a function definition from our models, I can't seem to extract the file name of my uploaded document. Below I tried the following template format but either results from my desired output:

.html Version 1

<form action="." method="GET">
{% if documents %}
   <ul>
      {% for document in documents %}
        <li> {{ document.docfile.filename }}
        <input type = "submit" name="load-data" value="Add to Layer"/>
        </li>
      {% endfor %}
  </ul>

Result: It just shows the button.

.html Version 2

<form action="." method="GET">
{% if documents %}
   <ul>
      {% for document in documents %}
        <li> {{ document.filename }}
        <input type = "submit" name="load-data" value="Add to Layer"/>
        </li>
      {% endfor %}
  </ul>

Result: It just shows the button.

.html Version 3

<form action="." method="GET">
{% if documents %}
   <ul>
      {% for document in documents %}
        <li> {{ document.docfile.name }}
        <input type = "submit" name="load-data" value="Add to Layer"/>
        </li>
      {% endfor %}
  </ul>

Result: Prints the complete pathname (eg: /documents/2016/10/08/filename.csv) together with the button

Here's the rest of my code:

models.py

class Document(models.Model):
     docfile = models.FileField(upload_to='document/%Y/%m/%d')

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

views.py

documents = Document.objects.all()
return render(request, 'gridlock/upload-data.html',
              {
               'documents' : documents,
               'form': form
              })

I hope someone can explain why everything I tried: {{ document.docfile.filename }} or {{document.file.filename}} or {{document.filename}} won't work either for me? Thanks!


Solution

  • I think you got pretty close with {{ document.filename }}, except in your models you need to change

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

    into

    def filename(self):
        # try printing the filename here to see if it works
        print (os.path.basename(self.docfile.name))
        return os.path.basename(self.docfile.name)
    

    in your models the field is called docfile, so you need to use self.docfile to get its value.

    source: django filefield return filename only in template