Reputation: 100
I have a views.py that:
After that, I want this .zip to be automatically downloaded. I did some research and tested some codes but none worked.
I created a "temp" folder in the root of the app where the created files are stored.
simplified view.py
def generate_ws(request,cource,ca_id):
ca = get_object_or_404(CreditAnalysis,pk=ca_id)
ca_owners = CAOwner.objects.filter(ca_operation=ca)
mo_farms = MOFarm.objects.filter(ca_operation=ca)
misses = []
generate_owner_mo(ca_owner,misses,city)
zip_name = 'temp/MOs - ' + str(ca_owner.owner) + '.zip'
zf = zipfile.ZipFile(zip_name,'w')
zf.close()
generate_farm_mo(mo_farm,misses,city)
generate_production_mo(ca,misses,city,production_city,pks)
files = glob.glob('temp/*.xlsx') #SELECT FILES AND PUT IN .ZIP
for file in files:
file_key = file.split('.')[0]
file_key=file_key.split(' - ')
for ca_owner in ca_owners:
zip_name = 'temp/MOs - ' + str(ca_owner.owner) + '.zip'
if str(ca_owner.owner) in file_key:
zf = zipfile.ZipFile(zip_name,'a')
new_file_name = file[5:]
zf.write(file,new_file_name)
zf.close()
break
files = glob.glob('temp/*.zip') # GET .ZIP FILES
for file in files:
download_mo(request,file) # CREATE A DOWNLOAD FOR EACH .ZIP FILE
misses = list(set(misses))
return render(request,'generate_mo.html',{'misses':misses,})
download_mo
def download_mo(request,file):
path_to_file = os.path.realpath(file)
with open(path_to_file,'rb') as fh:
response = HttpResponse(fh.read())
file_name = file[5:] #WITHDRAW "temp/"
response['Content-Disposition'] = 'inline; filename=' + file_name
return response
Everything works correctly except the download which never starts
Upvotes: 2
Views: 5543
Reputation: 1038
In order to download a file, you need to return a FileResponse
to the user. However, calling an external function that returns a FileResponse
won't work because you're not actually returning the FileResponse
to the user, in your case, the user only receives the render(request, 'generate_mo.html', {'misses':misses,})
so that won't download the files.
You can't download several files one after the other, so I suggest putting them all in a .zip or .tar file so that you can download them as only one file, and only need to return one FileResponse
.
As you also need to render your template, you can redirect to your download_mo
view on template loading so that your file is downloaded while your template is rendered.
Now, for your download_mo
view, replace your HttpResponse
with a FileResponse
:
from django.http import FileResponse
def download_mo(request,file):
path_to_file = os.path.realpath(file)
response = FileResponse(open(path_to_file, 'rb'))
file_name = file[5:]
response['Content-Disposition'] = 'inline; filename=' + file_name
return response
Upvotes: 4