简体   繁体   中英

Django Model Admin with FileField cannot read file in save_model after reading file when validating

I have a model with a FileField and I want to read the contents of the file before saving it in the Django admin. I need to verify the file is formatted correctly and also to parse version information out of it and save it into the model. I have written code for validation and can successfully validate the file, but it seems I cannot save the version information from the file in the save_object method after i successfully run the validation. If i skip using the validation, the code in the save_object method works as expected and I can read the file contents and save the version information into the model. I just can't get them to both work at the same time.

# models.py:

# the validation works
def validate_file_contents(value):
        contents = value.read()
        first_line, rest_of_file = contents.split('\n', 1)
        if not validate_file_format(rest_of_file):
            raise ValidationError("File is not formatted correctly.")
        if not parse_version(first_line):
            raise ValidationError("The file does not contain correctly formatted version information.")

class MyModel(models.Model):
    file = models.FileField(validators=[validate_file_contents])
    version = models.CharField(max_length=100, null=True, blank=True)

# admin.py:

class MyModelAdmin(admin.ModelAdmin):
    fields = ['file',]
    list_display = ['file', 'version']
    list_filter = ['file', 'version']

    def save_model(self, request, obj, form, change):
        contents = request.FILES['file'].read()
        # contents is empty after successful validation! It is not empty if validation is skipped.

        first_line = contents.split('\n', 1)[0]
        obj.version = parse_version(first_line)
        obj.save()

How can I both validate the file and save the version information? I am using Django 1.10 and Python 2.7.

read() works the way that it uses a pointer of position which you are reading from the file. So as you read the file, the pointer moves toward its end, until it's on the very end. So calling read() again will return nothing, because you're pointing on the end of the file now.

To read the file again, use seek(0) first, which will move the pointer to the start of the file again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM