Как я могу предварительно обработать содержимое файла, сохраняемого в поле FileField в Django?
В Django 2.2..csv
сохраняется FileField
в
Перед сохранением, я хочу удалить некоторые строки в нем.
Вот что у меня есть на данный момент:
# A Custom File Field that will modify the file contents before saving it
class CustomFileField(models.FileField):
# The method that gets called before the save happens
def pre_save(self, model_instance, add):
file_field = super().pre_save(model_instance, add)
file_field = self.update_file_contents(file_field)
return file_field
def update_file_contents(self, file_field):
# NEED TO SOMEHOW UPDATE THE CONTENTS OF
# THE file_field HERE BEFORE RETURNING IT
return file_field
# The model that uses this Custom File Field
class MyModel(models.Model):
my_csv_file = CustomFileField(upload_to='results/%Y/%m/%d/')
Я не совсем понимаю, что должен сделать мой метод update_file_contents
, чтобы обновить содержимое файла. Был ли файл сохранен в файловой системе к моменту вызова моего метода? Или он все еще находится в памяти?
Или мне следует забыть о создании пользовательского FileField
и просто переопределить метод MyModel
моего save
, чтобы после сохранения файла в файловой системе я снова открыл его и изменил, как любой другой файл?
Посмотрев на родительский класс (models.FileField
), я смог написать этот код, который, насколько я могу судить, делает то, что я хочу:
# A Custom File Field that will modify the file contents before saving it
class CustomFileField(models.FileField):
# The method that gets called before the save happens
def pre_save(self, model_instance, add):
file = models.Field.pre_save(self, model_instance, add)
if file and not file._committed:
self.modify_content(file, model_instance)
file.save(file.name, file.file, save=False)
return file_field
def update_file_contents(self, file, model_instance):
# Create a temporary backup of file contents in memory
contents = file.read().decode("utf-8")
# Delete the file contents from memory
file.seek(0)
file.truncate()
# Re-add the file contents, line by line, if the line passes validation
for line in contents.splitlines():
if self._line_passes_validation(line, model_instance):
file.write(line.encode("utf-8"), + b"\n")
def _line_passes_validation(self, line, model_instance):
"""
Looks at line (str), and decides if it passes validation.
Returns True if it does, or False if it doesn't.
model_instance can be used to check related fields in the database, which can help in the decision
"""
...
# The model that uses this Custom File Field
class MyModel(models.Model):
my_csv_file = CustomFileField(upload_to='results/%Y/%m/%d/')
Насколько я понимаю, когда файл загружается, он полностью сохраняется в оперативной памяти. Здесь, прежде чем он будет сохранен на диск с помощью file.save(...)
, я изменяю содержимое файла, который мы собираемся сохранить, создавая резервную копию этого содержимого и добавляя его заново, только если каждая строка проходит проверку.
Есть ли какие-либо проблемы с тем, чтобы сделать это таким образом?