Link to download a file

92 views
Skip to first unread message

giuseppe ricci

unread,
Aug 31, 2017, 11:58:27 AM8/31/17
to Django users
Hi guys, I need some help to insert a link to download a file. In a view I read data from a csv file and I show them in a table in a template. Under the table I need to insert, when there are data, 
a link similar as Download data and when user click it, he download the datafile, previously I wrote the same data in a csv file. You can see a part of interested view and the template to show data. 
In the code doesn't download anything.

views.py 

listafile = os.listdir('static/dati')

        fileok=[]
        context={}
        i=0
        for file in listafile:
            inizio=str(file[0:4]).strip()
            if inizio==anno:   
                fileok.append(file)
            elif inizio=='coun':
                contaf=str(file[6:10]).strip()
                if contaf==anno:
                    fileok.append(file)
            else:
                pass #print "File NON trovato", inizio, anno
        
        for nomefile in fileok:
            nomedato=str(nomefile[5:-4]).strip()
            if nomedato==tipodati:
                path2file=str(("static/dati/"+str(nomefile)).strip())
                with open(path2file) as f:
                    for line in f:
                        riga = line.split(";")
                        if riga[0]==cciaa:
                            context[i]=line
                            i=i+1
        #print "context", context

        d2 = {  k:v.split(";") for k,v in context.items() }
        j=0
        datilist={} 
        field_names = ['Provincia CCIAA', 'Data Ora', 'Numero REA', 'Forma Giuridica', 'Count dati']
        f=open('static/tmp/dati.csv', 'w') 
        writer = csv.writer(f) #questa definisce la variabile writer usata x scrivere i dati nel file csv!!!
        writer.writerow(field_names)

        while j<len(d2):
            datilist[j]=[d2[j][0], d2[j][3], d2[j][5], d2[j][7], d2[j][10].rstrip(), ''] #
            writer.writerow(datilist[j])
            j=j+1      
        
        return render_to_response('showdata.html', context_instance=RequestContext(request, {'dictdati': datilist} )) 
    
    else:

        return render_to_response('home.html', context_instance=RequestContext(request, {'var': d} ))


def showdata(request):
    return render_to_response('showdata.html', context_instance=RequestContext(request, context))

showdata.html
<div class="container">
        <div class="jumbotron">
        <h1>Statistiche Dkey</h1>
        <p>Ecco in forma tabellare i dati richiesti..</p>
  
        <form method="post" action="/getdata/">

            <style>
              table { width: 90%; background-color: #FFFFFF; color: #000000; }
              th, td { width: 4%; }
            </style>
    
              <table border="0" cellspacing="0" cellpadding="0" align="center">
                <thead>
                <tr>
                  <th>Nome</th>
                  <th>Data_Ora</th>
                  <th>Numero</th>
                  <th>Forma</th>
                  <th>Count</th>
                         
                </tr>
                </thead>
                <tbody>
                 
                <tr> 
                      
                  {% for key, item in dictdati.items %}   
                     
                      {% for idx in item %} 
                        {% if idx != '' %}                     
                          <td>{{ idx }}</td>
                        {% else %}
                        <tr><td></td></tr>
                        {% endif %}
                      {% endfor %}  
                 
                  {% endfor %}    
                <tr>
                </tbody>
              </table>
        </form>

        <p><a href="{{ MEDIA_URL }}/dati.csv">Download dei dati</a><p>

        </div>
    </div> <!-- /container -->




Can someone give me some suggestion? Other posts didn't aided me. 
Thanks.

James Schneider

unread,
Sep 1, 2017, 3:57:07 AM9/1/17
to django...@googlegroups.com


On Aug 31, 2017 8:57 AM, "giuseppe ricci" <peppep...@gmail.com> wrote:
Hi guys, I need some help to insert a link to download a file. In a view I read data from a csv file and I show them in a table in a template. Under the table I need to insert, when there are data, 
a link similar as Download data and when user click it, he download the datafile, previously I wrote the same data in a csv file. You can see a part of interested view and the template to show data. 
In the code doesn't download anything.

There's a few ways to handle this. 

1. Your 'download' button could simply be a link back to the same page with an additional GET argument (ie ?download= ). In your view, you would generate the data dict normally. Before you start returning responses though, you would check for the presence of the 'download' GET argument via request.GET.get('download', False). If you get anything but False (meaning they clicked the link), you can tweak the response headers and send back only the data you've gathered:


Depending on what kind of file you are returning, you may need to create an in memory file using StringIO or BytesIO and return that.

If you want to have a separate view handle the file download, simply add something like '/download/' to the end of the URL as another urls.py entry, and assume that the user wants to download the file within the view you specify for your URL. If you do that, I suggest you break out the CSV reading/writing logic (along with and file creation work) in to separate functions from the view so that both views access the data in the same way, they simply render and return it differently.

Another way would be to accept a POST submission through a form and then return the file as I explained above.

-James


giuseppe ricci

unread,
Sep 6, 2017, 9:03:57 AM9/6/17
to Django users
Thank you James for your reply..
So in my urls.py I insert a new entry:

url(r'^download/$', 'views.download')

and my view to download a file is:

def download(request):
file_path = 'static/tmp/' #settings.MEDIA_ROOT
return render_to_response('download.html', file_path+'dati.csv')

and the download.html is a simple page with a write Download file ok..
But in this manner I receive the error

TemplateDoesNotExist at /download/

static/tmp/dati.csv

Can you help me?
Thanks.

James Schneider

unread,
Sep 6, 2017, 1:23:51 PM9/6/17
to django...@googlegroups.com
On Wed, Sep 6, 2017 at 6:03 AM, giuseppe ricci <peppep...@gmail.com> wrote:
Thank you James for your reply..
So in my urls.py I insert a new entry:

url(r'^download/$', 'views.download')

and my view to download a file is:

def download(request):
file_path = 'static/tmp/' #settings.MEDIA_ROOT
return render_to_response('download.html', file_path+'dati.csv')




Your view should look similar to what the Django docs show here:


Is this a file that is publicly available? If so, it may be more efficient to have the web server process handle the download directly rather than Django. That would require a working setup for your STATIC_DIR and MEDIA_DIR. 

If that's the case, simply add a link to the file URL directly, something like this in your template:

<a href="{{ file_path }}">Download</a> 

Where {{ file_path }} is a path to the file in your media or static files (if the file changes, use the media directory, if it stays the same, use the static directory). Your web server should be configured to serve your MEDIA_URL and STATIC_URL already.

This site appears to have several approaches detailed: http://voorloopnul.com/blog/serving-large-and-small-files-with-django/
 
-James 

giuseppe ricci

unread,
Sep 7, 2017, 4:33:56 AM9/7/17
to Django users
Thanks.
My solution:

urls.py
url(r'^download/$', 'views.download', name='download'),

template.html
<p><a href="/download/">Download dei dati</a><p><p><a href="home">Indietro</a></p>

views.py
def download(request):
data = open(os.path.join(settings.MEDIA_ROOT, 'static/tmp/dati.csv'), 'r').read()
resp = HttpResponse(data, mimetype='application/x-download')
resp['Content-Disposition'] = 'attachment; filename=dati.csv'
return resp
it works!


Il giorno giovedì 31 agosto 2017 17:58:27 UTC+2, giuseppe ricci ha scritto:

Andréas Kühne

unread,
Sep 7, 2017, 4:50:50 AM9/7/17
to django...@googlegroups.com
Hi,

I would recommend that you checkout how django uses storage backends. The reason for that is that if you would like to use your application with a cloud provider that has a storage solution - for example S3, your code won't work the way it is written now. 

However if you just make some minor changes - it will work directly without any major problems.

Just do this:

view.py

from django.core.files.storage import default_storage

def download(request):
    data = default_storage.open('static/tmp/dati.csv').read()
    resp = HttpResponse(data, mimetype='application/x-download')
    resp['Content-Disposition'] = 'attachment; filename=dati.csv'
    return resp

Like I said, the reason for this is that you in the case don't have to handle the MEDIA_ROOT settings yourself and it all works the same anyway. Should you decide to move to a cloud provider that has some sort of storage - you can then use the django-storages package and easily connect it, without changing your code.

Regards,

Andréas

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/1fca0b1e-a952-4694-9bdb-177f1ac6b69c%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages