Как я могу предварительно обработать содержимое файла, сохраняемого в поле 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(...), я изменяю содержимое файла, который мы собираемся сохранить, создавая резервную копию этого содержимого и добавляя его заново, только если каждая строка проходит проверку.

Есть ли какие-либо проблемы с тем, чтобы сделать это таким образом?

Вернуться на верх