5

我有一个这样的模型:

class Talk(BaseModel):
  title        = models.CharField(max_length=200)
  mp3          = models.FileField(upload_to = u'talks/', max_length=200)
  seconds      = models.IntegerField(blank = True, null = True)

我想在保存上传的文件是 MP3 之前验证,如下所示:

def is_mp3(path_to_file):
  from mutagen.mp3 import MP3
  audio = MP3(path_to_file)
  return not audio.info.sketchy

一旦我确定我有一个 MP3,我想将谈话的长度保存在 seconds 属性中,如下所示:

audio = MP3(path_to_file)
self.seconds = audio.info.length

问题是,在保存之前,上传的文件没有路径(见这张票,关闭为wontfix),所以我无法处理 MP3。

我想提出一个很好的验证错误,以便ModelForms 可以显示一个有用的错误(“你这个白痴,你没有上传 MP3”或其他东西)。

知道如何在保存文件之前访问文件吗?

ps 如果有人知道验证文件的更好方法是 MP3,我会全力以赴 - 我也希望能够处理 ID3 数据(设置艺术家、专辑、标题和可能的专辑封面,所以我需要它是可处理的通过诱变剂)。

4

3 回答 3

10

您可以在视图中访问request.FILES中的文件数据。

我认为最好的方法是将上传的文件绑定到表单,覆盖表单的清理方法,从 clean_data 获取UploadedFile 对象,无论如何验证它,然后覆盖 保存方法并使用有关文件的信息填充模型实例,然后保存。

于 2010-05-09T19:25:44.280 回答
1

在保存之前获取文件的更简洁的方法是这样的:

from django.core.exceptions import ValidationError

#this go in your class Model
def clean(self):
    try:
        f = self.mp3.file #the file in Memory
    except ValueError:
        raise ValidationError("A File is needed")
    f.__class__ #this prints <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
    processfile(f)

如果我们需要一条路径,那么答案就在另一个问题中

于 2011-03-30T23:07:52.023 回答
0

您可以按照ImageField验证文件头的位置使用的技术,然后返回文件的开头。

class ImageField(FileField):
    # ...    
    def to_python(self, data):
        f = super(ImageField, self).to_python(data)
        # ...
        # We need to get a file object for Pillow. We might have a path or we might
        # have to read the data into memory.
        if hasattr(data, 'temporary_file_path'):
            file = data.temporary_file_path()
        else:
            if hasattr(data, 'read'):
                file = BytesIO(data.read())
            else:
                file = BytesIO(data['content'])

        try:
            # ...
        except Exception:
            # Pillow doesn't recognize it as an image.
            six.reraise(ValidationError, ValidationError(
                self.error_messages['invalid_image'],
                code='invalid_image',
            ), sys.exc_info()[2])
        if hasattr(f, 'seek') and callable(f.seek):
            f.seek(0)
        return f
于 2018-08-02T16:09:22.657 回答