【问题标题】:How can I pass a string into a the .close() method of the FileResponse object?如何将字符串传递给 FileResponse 对象的 .close() 方法?
【发布时间】:2021-09-20 02:42:36
【问题描述】:

我正在更改 FileResponse 对象的 .close() 方法的行为。 FileResponse 是 StreamingHttpResponse 的子类,与 HttpResponse 对象非常相似。

我要做的是获取一串文本,将其保存到 .docx 中,将该 docx 发送到浏览器,然后删除该 docx。在我尝试删除 .docx 之前,一切正常。看起来我不能在发送响应之前删除文件,因为响应需要文件,但是在发送响应之后我什么也做不了,因为视图已经完成了任务并发送了响应。我发现的一个潜在解决方案是修改 FileResponse 对象(类似于 HttpResponse 对象)的 .close() 方法来删​​除文件。

太好了。但是,我不知道如何将文件的路径传递给 .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 success: 200”,所以我知道我正在取得一些进展,但我需要将视图中的文件路径传递给这个 .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 文件确实正在生成并作为下载发送到客户端,这是所需的行为,但我不想无限期地保留所有这些导出的文件。

【问题讨论】:

    标签: python python-3.x django class web


    【解决方案1】:

    您可以使用request_finished 信号结合线程隔离对象local 来实现响应成功后删除文件。 django 信号: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")
    

    【讨论】:

      猜你喜欢
      • 2019-11-16
      • 2010-09-20
      • 1970-01-01
      • 2013-03-02
      • 1970-01-01
      • 2013-11-06
      • 2017-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多