我有一个这样的模型:
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,我想在秒属性中保存谈话的长度,如下所示:
audio = MP3(path_to_file)
self.seconds = audio.info.length
问题是,在保存之前,上传的文件没有路径(请参阅this ticket,关闭为wontfix
),因此我无法处理MP3。
我想提出一个很好的验证错误,以便ModelForm
可以显示有用的错误(“你这个白痴,你没有上传MP3”或其他东西)。
知道如何在保存文件之前访问该文件吗?
P.S。如果有人知道验证文件的更好方法是MP3,我会全神贯注 - 我也希望能够搞乱ID3数据(设置艺术家,专辑,标题和专辑艺术,所以我需要它可以通过mutagen)。
答案 0 :(得分:9)
您可以在视图中访问request.FILES中的文件数据。
我认为最好的方法是bind uploaded files to a form,覆盖表单clean method,从cleaning_data获取UploadedFile object,无论如何都要验证它,然后覆盖save method和使用有关文件的信息填充模型实例,然后保存它。
答案 1 :(得分: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)
如果我们需要一条路径,那么答案就是in this other question
答案 2 :(得分: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