【问题标题】:Reading file data during form's clean method在表单的 clean 方法期间读取文件数据
【发布时间】:2011-02-17 21:26:36
【问题描述】:

所以,我正在努力实现my previous question 的答案。

这是我的模型:

class Talk(models.Model):
  title        = models.CharField(max_length=200)
  mp3          = models.FileField(upload_to = u'talks/', max_length=200)

这是我的表格:

class TalkForm(forms.ModelForm):
  def clean(self):
    super(TalkForm, self).clean()
    cleaned_data = self.cleaned_data

    if u'mp3' in self.files:
      from mutagen.mp3 import MP3
      if hasattr(self.files['mp3'], 'temporary_file_path'):
        audio = MP3(self.files['mp3'].temporary_file_path())
      else:
        # What goes here?
        audio = None # setting to None for now
      ...
    return cleaned_data

  class Meta:
    model = Talk

Mutagen 需要磁盘上类似文件的对象或文件名(我认为) - 第一种情况(上传的文件大于内存中处理的文件大小)工作正常,但是我不知道如何处理我得到的InMemoryUploadedFile。我试过了:

# TypeError (coercing to Unicode: need string or buffer, InMemoryUploadedFile found)
audio = MP3(self.files['mp3'])

# TypeError (coercing to Unicode: need string or buffer, cStringIO.StringO found)
audio = MP3(self.files['mp3'].file)

# Hangs seemingly indefinitely on my test file (~800KB)
audio = MP3(self.files['mp3'].file.read())

诱变剂有什么问题,还是我做错了?

rebus 回答后

在我的ModelAdmin 类中即时修改FILE_UPLOAD_HANDLERS 设置,如下所示:

def add_view(self, request, form_url='', extra_context=None):
  request.upload_handlers = [TemporaryFileUploadHandler()]
  return super(TalkAdmin, self).add_view(request, form_url, extra_context)

点击提交时收到以下错误 500:

上传处理完成后,您无法设置上传处理程序。

即使我尽可能早地这样做!

另外,我不确定我要返回的对象是否有 save 方法(我查看了 dir(self.files['mp3'].file)dir(self.files['mp3']))。

【问题讨论】:

    标签: django django-file-upload mutagen


    【解决方案1】:

    您可以尝试更改您的FILE_UPLOAD_HANDLERS,以便 Django 始终使用临时文件处理程序:

    FILE_UPLOAD_HANDLERS 默认:

    ("django.core.files.uploadhandler.MemoryFileUploadHandler",
     "django.core.files.uploadhandler.TemporaryFileUploadHandler",)
    

    因此,您可以通过覆盖 settings.py 中的设置来仅保留 TemporaryFileUploadHandler

    编辑:

    简单多了,一开始就应该想到的:(:

    from your.models import Talk
    mp3 = self.files['mp3']
    f = Talk.mp3.save('somename.mp3', mp3)
    MP3(f.mp3.path)
    >>> {'TRCK': TRCK(encoding=0, text=[u'5'])}
    

    您可以通过这种方式将InMemoryUploadedFile 保存到磁盘,然后使用该文件的路径来处理mutagen

    编辑:

    没有模型实例也是如此。

    import os
    
    from django.core.files.storage import default_storage
    from django.core.files.base import ContentFile
    from django.conf import settings
    
    from mutagen.mp3 import MP3
    
    mp3 = request.FILES['mp3'] # or self.files['mp3'] in your form
    
    path = default_storage.save('tmp/somename.mp3', ContentFile(mp3.read()))
    MP3(os.path.join(settings.MEDIA_ROOT, path))
    

    请注意,它将文件保存在 MEDIA_ROOT 中,当我尝试将其保存在其他任何地方时,我得到 SuspiciousOperation,因为您可以写入的位置有限制...您应该在检查后删除此文件,我猜是真实的东西会在你的模型上...

    path = default_storage.delete('tmp/somename.mp3')
    

    【讨论】:

    • 这在我的场景中有点棘手,因为我真的无法访问(或者更确切地说,不想猴子路径)相关的视图,即管理员添加对象和更改对象意见。
    • 实际上,您可以在您的ModelAdmin 定义中为该模型docs.djangoproject.com/en/dev/ref/contrib/admin/#other-methods 子类化这两个视图
    • @rebus - 感谢您的帮助,但运气不佳 - 请参阅我的编辑。还有其他想法吗?
    • @Dominic Rodger 我已经编辑了一个答案,这应该更简单,事实证明,在管理视图(访问request.POST) 来更改upload_handlers。
    • @rebus - 非常好 - 非常感谢帮助我解决这个问题!还没有机会尝试,但一旦有机会我会告诉你的!
    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 2015-07-06
    • 2010-10-31
    • 2017-09-01
    • 2010-10-13
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多