Django как создать tmp excel файл и вернуть его браузеру в ответе

У меня есть процесс для создания tmp-файла и последующего возврата его в браузер в формате csv. Теперь я хочу сделать то же самое, но вернуть файл excel.

Итак, что у меня есть для csv - это представление в django, которое делает:

def export_wallet_view(request):

   tmp = tempfile.NamedTemporaryFile(delete=False)
   with open(tmp.name, 'w', encoding="utf-8-sig") as fi:
        csv_headers = [
            'Id',
            'Name'        
        ]
        fi.write(';'.join(csv_headers))
        fi.write('\n')

        //here also i save the rows into the file

  response = FileResponse(open(tmp.name, 'rb'))
  response['Content-Disposition'] = 'attachment; filename="wallet.csv"'
  return response

Чтобы преобразовать его в excel, я пытаюсь сделать что-то вроде этого, используя pandas:

df = pd.read_csv(tmp.name)
    
df.to_excel('pandas_to_excel.xlsx', sheet_name='new_sheet_name')

Проблема в том, что это создает excel на сервере, а я хотел бы сделать что-то вроде:

df = pd.read_csv(tmp.name)
    
df.to_excel('pandas_to_excel.xlsx', sheet_name='new_sheet_name') //this being a tmp file

response = FileResponse(open(tmp.name, 'rb')) //this should be the new excel tmp file
response['Content-Disposition'] = 'attachment; filename="wallet.csv"'
return response

Спасибо

Я не понимаю вашей проблемы.

Вы должны использовать один и тот же 'pandas_to_excel.xlsx' в обоих

df.to_excel('pandas_to_excel.xlsx', ...)

... open('pandas_to_excel.xlsx', 'rb')

или одинаковые tmp.name в обоих

df.to_excel(tmp.name, ...)

... open(tmp.name, 'rb')

Вы можете даже использовать еще раз NamedTemporaryFile() для создания нового временного имени.

tmp = tempfile.NamedTemporaryFile(delete=False)

df.to_excel(tmp.name, ...)

... open(tmp.name, 'rb')

Но популярным методом является использование io.String() или io.Bytes() для создания файлоподобного объекта в памяти - без создания файла на диске.

def export_wallet_view(request):

    csv_headers = ['Id', 'Name']

    file_like_object = io.Bytes()
    
    file_like_object.write(';'.join(csv_headers).encode('utf-8-sig'))
    file_like_object.write('\n'.encode('utf-8-sig'))    
    file_like_object.write('other rows'.encode('utf-8-sig'))
    
    file_like_object.seek(0)  # move to the beginning of file

    response = FileResponse(file_like_object)
    
    response['Content-Disposition'] = 'attachment; filename="wallet.csv"'
  
    return response

Для excel это может быть что-то вроде этого. Я использую io.String() для чтения csv непосредственно в pandas, а затем я использую io.Bytes() для создания файлоподобного объекта с данными excel.

def export_wallet_view(request):

    csv_headers = ['Id', 'Name']
    
    text = ';'.join(csv_headers)
    text += '\n'
    text += 'other rows'

    df = pd.read_csv(io.String(text))
    
    file_like_object = io.Bytes()
    df.to_excel(file_like_object)

    file_like_object.seek(0)  # move to the beginning of file

    response = FileResponse(file_like_object)
    
    response['Content-Disposition'] = 'attachment; filename="pandas_to_excel.xlsx"'
  
    return response
Вернуться на верх