代码之家  ›  专栏  ›  技术社区  ›  Dominic Rodger

在保存对象之前处理文件上载

  •  5
  • Dominic Rodger  · 技术社区  · 14 年前

    我有一个这样的模型:

    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
    

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

    问题是,在保存之前,上传的文件没有路径(请参阅 this ticket ,关闭为 wontfix ),所以我无法处理MP3。

    我想提出一个很好的验证错误 ModelForm s可以显示一个有用的错误(“你这个白痴,你没有上传MP3”之类的)。

    p、 如果有人知道一个更好的方法来验证文件是mp3我洗耳恭听-我也希望能够乱用ID3数据(设置艺术家,专辑,标题,可能专辑艺术,所以我需要它是可处理的 mutagen ).

    3 回复  |  直到 14 年前
        1
  •  9
  •   Davor Lucic    14 年前

    您可以访问中的文件数据 request.FILES 在你看来。

    我认为最好的办法是 bind uploaded files to a form clean method ,获取 UploadedFile object save method 并用有关文件的信息填充模型实例,然后保存它。

        2
  •  1
  •   Community Egal    7 年前

    在保存之前获取文件的更简洁的方法如下:

    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)
    

    如果我们需要一条路,答案是 in this other question

        3
  •  0
  •   Don Kirkby    6 年前

    你可以遵循 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