0

I have a table which presents order information - attached to each order is a file. This file's file path displays as a link in the table already, but I am unable to download by clicking it. I would like to be able to click this link and have the proper .docx download.

I am referencing: how to download a filefield file in django view

but I really don't understand how this solution is working. Is no URL needed? How does the view know which file to pick? I opened a previous question and got marked as a duplicate and pointed to this link, but I really don't understand the solution that was given here. Do I need to somehow pass the pk of the order or something? Any help would be greatly appreciated. Below is my code.

models.py

class Orders(models.Model):

...

order_file = models.FileField(upload_to='web_unit', null=True, blank=True)

...
    def __str__(self):

       return self.reference

index.html

<div class="table-responsive">
<table id="main_table" class="table table-striped table-bordered" cellspacing="0" style="width="100%">
  <thead>
    <tr>
      ....
  </thead>

  <tbody>

    {% for order in orders %}

    <tr>

      <td>
        <!-- Update book buttons -->
      <button type="button" class="update-book btn btn-sm btn-primary" style="color: #FFCF8B; border-color: #FFCF8B; background-color: #FFF;" data-id="{% url 'order_update' order.pk %}">
        <span class="fa fa-pencil"></span>
      </button>
      </td>

   ....

      <td><a href="{{ order.order_file.url }}">Download</a></td> #this is the link

    </tr>
    {% endfor %}


  </tbody>
</table>

When the link in the table is clicked - I'd like for the file to be downloaded - I need help on how to define the URL and the View to make this happen.

Right now when I click the link I get an error showing all the urls that were tried.

GXM100
  • 417
  • 6
  • 20

1 Answers1

-1

This is a bit complex stuff at first, but let me break it down for you.

First of all, the files you upload thorough Django are stored somewhere in the Filesystem (in case of default settings). This usually means your uploaded files go to your /media folder which is in the same directory as your other Django files are. The path to the media folder can be defined in your Django settings file using the MEDIA_ROOT parameter. By default its probably next to your manage.py file.

To be able to download your uploaded files, you need to serve the files using a webserver (Apache, nginx, etc...). Here's a config snippet from a classic nginx setup:

# Media files
    location /media {
        alias /home/riverman/my-django-project/media;
    }

This means, your uploaded file could be accessed (and downloaded) thorough a browser using the following imaginary link:
http://my-django-project.test/media/images/cat.png

Now here's the tricky part: Django does not store the full url (http://my-django-project.test/media/images/cat.png) to your file in the database, but instead, only the static part of it (/images/cat.png). Both the media folder's name (media in this example) and the website's URL (my-django-project.test) are subject to later change so it would not be clever to store it all in the database, but instead, you generate the full URL on-the-fly.

When you access the path to your desired file ({{ order.order_file.url }}) you only receive a partial information, something like this: /media/images/cat.png.

You need to combine this partial information with your site's url. Here's an example how i'd do it. Add this in your views.py:

from django.contrib.sites.models import Site

current_site = Site.objects.get_current()
current_site.domain

and update your index.html to this:

<td><a href="{{ current_site.domain }}/{{ order.order_file.url }}">Download</a></td>

To setup a local webserver on your development machine is out of scope for this question, but you can refer to this question: Best lightweight web server (only static content) for Windows

Good luck!

Riverman
  • 503
  • 6
  • 17