在 Django 中保存包含 FileField 的模型
Saving a model containing a FileField in Django
我有以下型号;
class AudioFile(models.Model):
name = models.CharField(max_length=100, default='')
audio_file = models.FileField()
uploader = models.ForeignKey(User, default='')
def __unicode__(self):
return self.name
下表;
class AudioFileForm(forms.ModelForm):
class Meta:
model = AudioFile
fields = ['name', 'audio_file']
def clean_audio_file(self):
audio = self.cleaned_data.get('audio_file',False)
if audio:
if audio._size > 5*1024*1024:
raise ValidationError("File too large ( > 5mb )")
if os.path.splitext(audio.name)[1] != ".mp3":
raise ValidationError("We only support mp3!")
return audio
else:
raise validationError("Couldn't read uploaded file")
如您所见,有一些自定义验证
然后我将下面的 html 与 AudioFileForm
作为 form
;
传递
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="post" action="{% url 'actual_upload_audio' %}">
{% csrf_token %}
{{ form }}
<input type="submit" value="Upload"/>
</form>
</body>
</html>
现在我知道如果对象不包含 FileField 如何保存它。我会做这样的事情;
form = AudioFileForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
//Say it contained another field, foo
foo = form.cleaned_data['foo']
uploader = request.user //view requires login
audio_file = Audio_File.objects.create(name=name,
foo=foo,
uploader=uploader)
audio_file.save()
return HttpResponse("Success!")
但是有一个 FileField 有问题我不知道如何处理它。我阅读了 Django 的文档,但并没有真正理解它。一个更简单详细的解释会很可爱。
首先,我的 settings.py
中有 MEDIA_ROOT = '/home/afzalsh/works/openradio/audio_files/'
更新
感谢@Rohan,我现在有 <form method="post" action="{% url 'actual_upload_audio' %}" enctype="multipart/form-data">
而不是 <form method="post" action="{% url 'actual_upload_audio' %}">
感谢@dzejdzej,还有以下视图;
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['uploader'] = request.user
form.save()
return HttpResponseRedirect(reverse('home_audio',kwargs={'pk':audio_file.pk}))
else:
return HttpResponse("Form Invalid!")
但是Form Invalid!
:/
您的表单应具有 enctype="multipart/form-data"
属性,以便提交文件。
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
您应该提及 upload_to 属性:audio_file = models.FileField(upload_to='uploads')
此处 'uploads' 是您要将文件上传到的目录的名称。
既然您使用的是 ModelForm,为什么不让 Django 处理保存整个模型?
from django.shortcuts import redirect
form = AudioFileForm(request.POST)
if form.is_valid():
form.cleaned_data['uploader'] = request.user //view requires login
form.save()
return redirect(success_url)
如果您使用的是 Django >=1.7,则不再需要 upload_to 字段。但是,我认为这是一个很好的做法。
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.FileField.upload_to
成功后也重定向用户 POST 以避免 csrf 问题。
作为Rohan
seaid,您必须像这样在模板中污染您的表格。
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
这允许您将请求的文件发送到 view
。现在看来你一定有这样的东西:
def my_view(request):
if request.method == 'POST':
my_form = MyForm(request.POST, request.FILES)
if my_form.is_valid():
my_form.save()
您可以使用 request.FILES
初始化表单 FileField 和 ImageField
我有以下型号;
class AudioFile(models.Model):
name = models.CharField(max_length=100, default='')
audio_file = models.FileField()
uploader = models.ForeignKey(User, default='')
def __unicode__(self):
return self.name
下表;
class AudioFileForm(forms.ModelForm):
class Meta:
model = AudioFile
fields = ['name', 'audio_file']
def clean_audio_file(self):
audio = self.cleaned_data.get('audio_file',False)
if audio:
if audio._size > 5*1024*1024:
raise ValidationError("File too large ( > 5mb )")
if os.path.splitext(audio.name)[1] != ".mp3":
raise ValidationError("We only support mp3!")
return audio
else:
raise validationError("Couldn't read uploaded file")
如您所见,有一些自定义验证
然后我将下面的 html 与 AudioFileForm
作为 form
;
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="post" action="{% url 'actual_upload_audio' %}">
{% csrf_token %}
{{ form }}
<input type="submit" value="Upload"/>
</form>
</body>
</html>
现在我知道如果对象不包含 FileField 如何保存它。我会做这样的事情;
form = AudioFileForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
//Say it contained another field, foo
foo = form.cleaned_data['foo']
uploader = request.user //view requires login
audio_file = Audio_File.objects.create(name=name,
foo=foo,
uploader=uploader)
audio_file.save()
return HttpResponse("Success!")
但是有一个 FileField 有问题我不知道如何处理它。我阅读了 Django 的文档,但并没有真正理解它。一个更简单详细的解释会很可爱。
首先,我的 settings.py
MEDIA_ROOT = '/home/afzalsh/works/openradio/audio_files/'
更新
感谢@Rohan,我现在有 <form method="post" action="{% url 'actual_upload_audio' %}" enctype="multipart/form-data">
而不是 <form method="post" action="{% url 'actual_upload_audio' %}">
感谢@dzejdzej,还有以下视图;
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['uploader'] = request.user
form.save()
return HttpResponseRedirect(reverse('home_audio',kwargs={'pk':audio_file.pk}))
else:
return HttpResponse("Form Invalid!")
但是Form Invalid!
:/
您的表单应具有 enctype="multipart/form-data"
属性,以便提交文件。
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
您应该提及 upload_to 属性:audio_file = models.FileField(upload_to='uploads')
此处 'uploads' 是您要将文件上传到的目录的名称。
既然您使用的是 ModelForm,为什么不让 Django 处理保存整个模型?
from django.shortcuts import redirect
form = AudioFileForm(request.POST)
if form.is_valid():
form.cleaned_data['uploader'] = request.user //view requires login
form.save()
return redirect(success_url)
如果您使用的是 Django >=1.7,则不再需要 upload_to 字段。但是,我认为这是一个很好的做法。 https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.FileField.upload_to
成功后也重定向用户 POST 以避免 csrf 问题。
作为Rohan
seaid,您必须像这样在模板中污染您的表格。
<form method="post" action="{% url 'actual_upload_audio' %}"
enctype="multipart/form-data" >
...
</form>
这允许您将请求的文件发送到 view
。现在看来你一定有这样的东西:
def my_view(request):
if request.method == 'POST':
my_form = MyForm(request.POST, request.FILES)
if my_form.is_valid():
my_form.save()
您可以使用 request.FILES