How to use Post-save Signal when uploading document, and saving before and after altering document?

Viewed 123

I want save document when uploaded and run pandas script and save that script but also to forward to user do download it. How to do it simple way?

This is how I tried to do it, upload and save upload works, but pandas script is not working.

def my_view(request):
    message = 'Upload as many files as you want!'
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            
            newdoc = Document(docfile=request.FILES['docfile'])
            
            newdoc.save()
            
            #This part is doing calculations for uploaded file
            dfs = pd.read_excel(newdoc, sheet_name=None)
            with pd.ExcelWriter('output_' + newdoc + 'xlsx') as writer:
                for name, df in dfs.items():
                    print(name)
                    data = df.eval('d = column1 / column2')
                    ooutput = data.eval('e = column1 / d')
                    ooutput.to_excel(writer, sheet_name=name)
                    output = io.BytesIO()
                    writer = pd.ExcelWriter(output, engine='xlsxwriter')
                    newdoc.to_excel(writer, index=False)
                    writer.save()
                    output.seek(0)
                    response = HttpResponse(output,
                        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
                    response['Content-Disposition'] = 'attachment; filename=%s.xlsx' % 'Download'
                    return response
            
            return redirect('results')
        else:
            message = 'The form is not valid. Fix the following error:'
    else:
        form = DocumentForm()  

    documents = Document.objects.all()

    context = {'documents': documents, 'form': form, 'message': message}
    return render(request, 'list.html', context)


def results(request):
    documents = Document.objects.all()
    context = {'documents': documents}
    return render(request, 'results.html', context) 
2 Answers
dfs = pd.read_excel(newdoc, sheet_name=None)

You are passing newdoc here, which is your model, not a IO object.

Try

dfs = pd.read_excel(newdoc.docfile, sheet_name=None)

or

 dfs = pd.read_excel(newdoc.docfile.file, sheet_name=None)

This is the not answer but my suggestion, you are following the wrong way of implementation.

  1. You can set background process in Celery
  2. After the job is done in Celery you can mail/notify the User with download URL.

The above given solution will be long but scalable and performance-oriented as well.

Related