#python #python-3.x #django #class #web
Вопрос:
Я изменяю поведение метода .close() объекта FileResponse. FileResponse-это подкласс StreamingHttpResponse, который очень похож на объект HttpResponse.
То, что я пытаюсь сделать, это взять строку текста, сохранить ее в файле .docx, отправить этот документ в браузер, а затем удалить этот документ. Все работает отлично, пока я не попытаюсь удалить .docx. Не похоже, что я могу удалить файл до отправки ответа, потому что ответ нуждается в файле, но я вообще ничего не могу сделать после отправки ответа, потому что представление выполнило свою задачу и отправило ответ. Потенциальным решением, которое я нашел, является изменение метода .close() объекта FileResponse (аналогично объекту HttpResponse) для удаления файла.
Здорово. Однако я не знаю, как передать путь к файлу методу .close (). Это может быть элементарный вопрос, но я обычно избегаю редактирования встроенных методов класса.
Код ниже.
import logging
from django.http import FileResponse
import os
logger = logging.getLogger("django")
#editing the default closing behavior of the file response object to delete the file
that it just sent.
class SendAndDeleteExport(FileResponse):
def close(self):
super(SendAndDeleteExport, self).close()
# do whatever you want, this is the last codepoint in request handling
logger.info(self)
# os.remove(desired_path "/export.docx"
if self.status_code == 200:
logger.info('HttpResponse successful: %s' % self.status_code)
Я получаю «HttpResponse успешно: 200» в консоли, поэтому я знаю, что добиваюсь некоторого прогресса, но мне нужно передать путь к файлу из представления в this .close()
views.py
from .helpers import SendAndDeleteExport
from docx import Document
import os
def export(request):
cwd = os.getcwd()
desired_path = os.path.join(cwd, 'exports')
logger.info(desired_path)
document = Document()
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet. edited againa')
document.save(desired_path "/export.docx")
file_to_user = SendAndDeleteExport(open(desired_path "/export.docx", 'rb'))
return file_to_user
Файл .docx действительно создается и отправляется клиенту в качестве загрузки, что является желаемым поведением, но я не хочу держать все эти экспортированные файлы бесконечно.
Ответ №1:
Вы можете использовать request_finished
объединение сигналов с объектом изоляции потоков local
для достижения такого удаления файла после успешного ответа. сигналы джанго: https://docs.djangoproject.com/en/3.2/ref/signals/#request-finished
django.core.signals.request_finished Отправляется, когда Django завершает доставку HTTP-ответа клиенту.
для получения более подробной информации, пожалуйста, смотрите: https://docs.djangoproject.com/en/3.2/topics/signals/
from threading import local
from django.core.signals import request_finished
from django.shortcuts import HttpResponse
local = local() # for threading isolation
def export(request):
# do something
local.path = 'your_file_path'
return HttpResponse('ok')
def when_request_finished(sender, **kwargs):
"""
this function will be executed when any request finished(got response)
"""
if hasattr(local, 'path'):
# do something
print(local.path)
request_finished.connect(when_request_finished, dispatch_uid="when_request_finished_identifier")