Django: le classeur de sauvegarde openpyxl en pièce jointe
Salut j'ai une question rapide. Je n'ai pas trouvé de réponse sur internet peut-être que quelqu'un d'entre vous peut m'aider.
alors je veux sauvegarder le classeur comme pièce jointe mais je ne sais pas comment laisse voir un exemple :
from openpyxl import Workbook
from openpyxl.cell import get_column_letter
wb = Workbook(encoding='utf-8')
dest_filename = 'file.xlsx'
ws = wb.worksheets[0]
ws.title = "range names"
for col_idx in xrange(1, 40):
col = get_column_letter(col_idx)
for row in xrange(1, 600):
ws.cell('%s%s'%(col, row)).value = '%s%s' % (col, row)
ws = wb.create_sheet()
ws.title = 'Pi'
ws.cell('F5').value = 3.14
Puis j'ai essayé :
response = HttpResponse(wb, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="foo.xls"'
return response
C'est le retour fichier xlsx en effet, mais dans le fichier il y a seulement l'objet adres pas le contenu du fichier:
<openpyxl.workbook.Workbook object at 0x00000000042806D8>
quelqu'un Peut-il aider ?
3 réponses
faire un essai:
from openpyxl.writer.excel import save_virtual_workbook
...
response = HttpResponse(save_virtual_workbook(wb), content_type='application/vnd.ms-excel')
save_virtual_workbook
a été spécialement conçu pour votre cas d'utilisation. Voici une docstring:
"""retourner un cahier d'exercices en mémoire, adapté à une réponse Django."""
j'ai l'habitude d'utiliser
ws = wb.add_sheet("Pi")
au lieu de
ws = wb.create_sheet()
ws.title = "Pi"
de plus, vous pouvez essayer de faire: (voir documentation)
wb.save(stream)
puis utiliser stream dans HttpResponse.
Sur au moins certaines versions de django/python/openpyxl, la solution donnée ne fonctionne pas. Voir https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data
Simple solution de travail:
wb = Workbook(write_only=True, encoding='utf-8')
ws = wb.create_sheet()
for row in data:
ws.append([str(cell) for cell in row])
response = HttpResponse(content_type='application/vnd.ms-excel')
wb.save(response)
ce qui se passe ici, C'est que le HttpResponse de Django est un objet qui ressemble à un fichier. Workbook.save()
peut prendre un fichier objet semblable. (En interne, il utilise zipfile, qui prend un nom de fichier ou un fichier-comme objet.)
si vous manipulez le fichier en mémoire, c'est la solution la plus simple et probablement la plus efficace. Une réponse en continu n'a pas vraiment de sens puisque les données ne sont pas créées avec un générateur. Même si save_virtual_workbook fonctionne, les données qu'il écrit sont générées sous forme de bloc avant qu'il ne soit lisible.
l'autre option serait de créer un fichier Temporaryfile nommé (à partir de tempfile ou Django wrapper), passez les dans Workbook.save()
, puis utilisez FileResponse pour le streamer à partir du système de fichiers au lieu de la mémoire.