使用基于 class 的视图重新打开关闭的 django InMemoryFileUpload

Reopening a closed django InMemoryFileUpload using class based views

我有一个 Django 项目,其中涉及用户通过表单上传 CSV 文件。我在forms clean方法中解析这个文件,然后在views form_valid方法中我想再次读取文件数据(为了长期存储的目的)。

我的问题是,在 clean 方法中解析文件后,我无法再对文件对象执行 IO 操作,任何尝试这样做都会引发错误。代码如下:

class MyForm(forms.Form):
    file = forms.FileField()
    def clean(self):
        cleaned_data = super().clean()
        file = cleaned_data["file"]
        reader = csv.DictReader(io.TextIOWrapper(file))
        for row in reader:
            ...  # process data
        return cleaned_data

class MyView(generic.FormView):
    form_class = MyForm

    def form_valid(self, form):
        file = form.files["file"]
        file.read()  # raises ValueError: I/O operation on closed file.

此时无法再调用其他方法,例如 file.open(),因为这会导致引发相同的异常。

令我感到困惑的是,在我的应用程序中还有其他示例可以在 form_valid 方法中对文件执行 IO 操作,示例如下:

class MyOtherForm(forms.Form):
    file = forms.FileField()

class MyOtherView(generic.FormView):
    form_class = MyOtherForm

    def form_valid(self, form):
        file = form.files["file"]
        file.read()  # this works, no error raised.

我对此的解释是,读取文件的过程以某种方式触发了它的关闭,尽管我不确定在何处或如何关闭。我想知道的是有什么方法可以防止文件在我读取后关闭,或者在文件关闭后重新打开?

我意识到我可以在同一个方法中执行初始 read/parse 和第二个,这应该可以解决我的问题。然而,那时我开始纠结我的担忧,所以宁愿避免它。

原来问题出在io.TextIOWrapper的使用上,在清理前通过调用text wrapper的detach方法解决了。

另一个 SO post 中涵盖了更详细的解释: