【问题标题】:Why won't my file save to instance (it saves to disk...)?为什么我的文件不能保存到实例(它保存到磁盘...)?
【发布时间】:2011-09-22 16:43:37
【问题描述】:

我可以让我的文件保存到我告诉它的磁盘,但不能让它保存到实例,我一点也不知道为什么!

models.py

    class Song(models.Model):
        name = models.CharField(max_length=50)
        audio_file = models.FileField(upload_to='uploaded/music/', blank=True)

views.py

    def create_song(request, band_id):
        if request.method == 'POST':
            band = Band.objects.get(id=band_id)
            form = SongForm(request.POST, request.FILES)
            if form.is_valid():
                handle_uploaded_file(request.FILES['audio_file'])
                form.save()
                return HttpResponseRedirect(band.get_absolute_url)
        else:
            form = SongForm(initial={'band': band_id})
        return render_to_response('shows/song_upload.html', {'form': form}, context_instance=RequestContext(request))

handle_uploaded_file

    def handle_uploaded_file(f):
        ext = os.path.splitext(f.name)[1]
        destination = open('media/uploaded/music/name%s' %(ext), 'wb+')
        for chunk in f.chunks():
            destination.write(chunk)
        destination.close()

song_upload.html(相关部分)

    {% block main %}
    {{band.name}}
        <form enctype="multipart/form-data" method="post" action="">{% csrf_token %}
           {{ form.as_p}}
           <input type="submit" value="Add song" />
        </form>
    {% endblock %}

forms.py

    class SongForm(forms.ModelForm):
        band = forms.ModelChoiceField(queryset=Band.objects.all(), widget=forms.HiddenInput) 
        def clean_audio_file(self):
            file = self.cleaned_data.get('audio_file',False)
            if file:
                if file._size > 10*1024*1024:
                    raise forms.ValidationError("Audio file too large ( > 10mb)")
                if not file.content_type in ["audio/mp3", "audio/mp4"]:
                    raise forms.ValidationError("Content type is not mp3/mp4")
                if not os.path.splitext(file.name)[1] in [".mp3", ".mp4"]:
                    raise forms.ValidationErorr("Doesn't have proper extension")
            else:
                raise forms.ValidationError("Couldn't read uploaded file")
        class Meta:
            model = Song

该文件就在媒体/上传/音乐中,但在管理中 audio_file 是空白的,如果我为 audio_file 设置空白 = False(这是我想要做的),我被告知此字段是必需的。什么给了??

提前致谢!已经在这家呆了一段时间了,文档对我来说似乎很轻松(newb)。

【问题讨论】:

  • 您还应该包含SongForm的代码!
  • 是的,没有 SongForm,我们无法判断发生了什么。

标签: django django-views django-file-upload


【解决方案1】:

clean_audio_file 应该返回此特定字段的清理数据,因此您需要向其添加 return file

来自django's documentation

就像一般领域clean() 方法,上面,这个方法应该 返回清理后的数据,无论 不管它改变了什么。

【讨论】:

  • 呸。这就是我没有仔细阅读的结果……我知道当你花时间帮助有问题的人时一定很沮丧,而他们没有仔细阅读你的回复。我真诚的道歉。 16 小时前你是对的!
【解决方案2】:

据我所知,您不需要handle_uploaded_file()。您正在使用ModelFormmodels.FileField。它支持upload_to参数,并自动将文件保存到目标。

从Django docs上传example的基本文件是使用Formforms.FileField,因此它涉及handle_uploaded_file()函数。

所以,试着简单地删除这一行:

handle_uploaded_file(request.FILES['audio_file'])

从你的角度来看,请告诉你接下来会发生什么。

编辑:另外,@lazerscience 是对的,您需要添加

return self.cleaned_data

clean_audio_file() 的末尾。 (但不是return file,因为即使你只清理一个字段,你也应该返回整个清理过的数据字典。)

【讨论】:

  • 进行了您提到的两项更改,现在收到一条错误消息:“dict”对象没有属性“_committed”。回溯只包含我自己编写的一行代码:form.save()。如果我删除 form.save() 我看不到错误,但表单也不会保存!像往常一样上传文件,谷歌不是特别有用,我不知道从哪里开始文档...提前谢谢!
  • 这很奇怪。好吧,看来我错了,@lazerscience 确实是对的,只需要从清理方法中返回文件。 (因为_committed 应该是文件字段状态的一部分,但它在cleaned_data 字典中不存在。)尝试使用return file 而不是return self.cleaned_data。不过,我仍然确定 models.FileField 将处理文件存储。
  • 非常感谢安东。 @lazerscience 的解决方案,加上删除 handle_uploaded_file() 效果很好!
猜你喜欢
  • 2012-08-27
  • 2016-02-19
  • 2016-07-22
  • 2013-12-19
  • 2010-09-23
  • 2010-11-08
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多