Повторное открытие закрытого django InMemoryFileUpload с помощью представлений на основе классов
У меня есть Django проект, в котором пользователь загружает CSV файл через форму. Я разбираю этот файл в методе forms clean, а затем в методе views form_valid я хочу снова прочитать данные файла (для целей долгосрочного хранения).
Моя проблема заключается в том, что после разбора файла в методе clean я больше не могу выполнять операции ввода-вывода для объекта файла, любая попытка сделать это вызывает ошибку. Код ниже:
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, пример ниже:
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.
Моя интерпретация этого заключается в том, что каким-то образом процесс чтения файла вызывает его закрытие, хотя я не уверен, где и как. Я хочу знать, есть ли способ предотвратить закрытие файла после его чтения или открыть его снова после закрытия?
Я понимаю, что могу выполнить и начальное чтение/разбор и второе в одном и том же методе, и это решит мою проблему. Однако на этом этапе я начинаю запутываться в своих проблемах, поэтому предпочел бы избежать этого.
Оказывается, проблема заключалась в использовании io.TextIOWrapper, она была решена вызовом метода detach на текстовой обертке до ее очистки.
Более подробное объяснение дано в другом посте SO: Почему TextIOWrapper закрывает данный поток BytesIO?