Django:表格成功但图片未上传
Django : Form Successful but image not uploaded
MODELS.PY
class Campaign(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
campaign_image = models.ImageField(default="profilepic.jpg",upload_to="campaign_pictures")
FORMS.PY
class RaiseFundsFrom3(forms.ModelForm):
class Meta:
model = Campaign
fields = ['campaign_image']
VIEWS.PY
@login_required
def raise_funds_medical_3(request):
if request.method == 'POST':
form = RaiseFundsFrom3(request.POST, request.FILES or None, instance=request.user)
if form.is_valid():
check = form.save(commit=False)
check.save()
return HttpResponse('form worked')
else:
form = RaiseFundsFrom3()
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
URLS.PY
path('raise/medical/photo', views.raise_funds_medical_3, name="raise_funds_medical_3"),
raise_funds_medical_3.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group pt-2">
<small>Photo formats must be PNG / JPG / JPEG</small>
<input type="file" name="campaign_image" />
</div>
<button class="btn btn-lg button_bfg_blue" type="submit"> <small><b> NEXT </b></small> </button>
</form>
在提交表单时,我没有收到任何错误,但图像没有上传到所需的文件夹。
但是,在 views.py 中的 raise_funds_medical_3 函数中,如果我删除 instance=request.user,图像会上传,但我会收到以下错误:NOT NULL 约束失败:funds_campaign.user_id
您的表单是 ModelForm
对应 Campaign
,因此它的 instance
需要是 Campaign
。不要将 request.user
分配为它的 instance
!
现在,您的表单不包括保存 Campaign
所需的 user
字段,因此您应该在保存到数据库之前在视图中自行分配它:
campaign = form.save(commit=False) # this gives your the form's instance
campaign.user = request.user # this assigns the user
campaign.save() # this commits to the database
您还应该处理表单无效的情况。这很简单,只需 un-indent 视图函数中的最后一个 return
,这样 return render(...)
也会被调用,以防 form
不存在无效。
最后,当表单有效时不要返回响应,重定向 到另一个视图是一个很好的做法。这样,当用户刷新页面时,就不会再次提交表单。您的最终代码应如下所示:
@login_required
def raise_funds_medical_3(request):
if request.method == 'POST':
form = RaiseFundsFrom3(request.POST, request.FILES or None)
if form.is_valid():
check = form.save(commit=False)
check.user = request.user
check.save()
return redirect(<url_pattern>)
else:
form = RaiseFundsFrom3()
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
补充回答
我已经完全讨厌 Django 基于函数的视图的传统结构。可以通过反转有效性测试并添加一行来重构它们,以便存在一个且只有一个表单实例。结果是 IMO 更容易阅读,并且很容易概括为显示两种或多种形式的视图。
def raise_funds_medical_3(request):
args = [request.POST, request.FILES or None] if request.method == "POST" else []
form = RaiseFundsFrom3(*args)
if request.method != "POST" or not form.is_valid():
# unbound form or form not valid
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
# form is valid so do the processing and redirect
check = form.save(commit=False)
check.user = request.user
check.save()
return redirect(<url_pattern>)
如果你想处理>1个表格,测试变成
if request.method != "POST" or any(
[ not form.is_valid(), not form2.is_valid(), ...]):
强制对所有表单进行 .is_valid()
评估,即使第一个表单无效,以便 所有 错误消息显示给用户。
在一个复杂的业务应用程序中,处理一个成功的表单提交可能比这个简单的例子多出好几行代码。把它放在最后,不缩进,与所有样板文件隔离开来,除了 return redirect(...)
,让事情变得容易多了!
MODELS.PY
class Campaign(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
campaign_image = models.ImageField(default="profilepic.jpg",upload_to="campaign_pictures")
FORMS.PY
class RaiseFundsFrom3(forms.ModelForm):
class Meta:
model = Campaign
fields = ['campaign_image']
VIEWS.PY
@login_required
def raise_funds_medical_3(request):
if request.method == 'POST':
form = RaiseFundsFrom3(request.POST, request.FILES or None, instance=request.user)
if form.is_valid():
check = form.save(commit=False)
check.save()
return HttpResponse('form worked')
else:
form = RaiseFundsFrom3()
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
URLS.PY
path('raise/medical/photo', views.raise_funds_medical_3, name="raise_funds_medical_3"),
raise_funds_medical_3.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group pt-2">
<small>Photo formats must be PNG / JPG / JPEG</small>
<input type="file" name="campaign_image" />
</div>
<button class="btn btn-lg button_bfg_blue" type="submit"> <small><b> NEXT </b></small> </button>
</form>
在提交表单时,我没有收到任何错误,但图像没有上传到所需的文件夹。 但是,在 views.py 中的 raise_funds_medical_3 函数中,如果我删除 instance=request.user,图像会上传,但我会收到以下错误:NOT NULL 约束失败:funds_campaign.user_id
您的表单是 ModelForm
对应 Campaign
,因此它的 instance
需要是 Campaign
。不要将 request.user
分配为它的 instance
!
现在,您的表单不包括保存 Campaign
所需的 user
字段,因此您应该在保存到数据库之前在视图中自行分配它:
campaign = form.save(commit=False) # this gives your the form's instance
campaign.user = request.user # this assigns the user
campaign.save() # this commits to the database
您还应该处理表单无效的情况。这很简单,只需 un-indent 视图函数中的最后一个 return
,这样 return render(...)
也会被调用,以防 form
不存在无效。
最后,当表单有效时不要返回响应,重定向 到另一个视图是一个很好的做法。这样,当用户刷新页面时,就不会再次提交表单。您的最终代码应如下所示:
@login_required
def raise_funds_medical_3(request):
if request.method == 'POST':
form = RaiseFundsFrom3(request.POST, request.FILES or None)
if form.is_valid():
check = form.save(commit=False)
check.user = request.user
check.save()
return redirect(<url_pattern>)
else:
form = RaiseFundsFrom3()
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
补充回答
我已经完全讨厌 Django 基于函数的视图的传统结构。可以通过反转有效性测试并添加一行来重构它们,以便存在一个且只有一个表单实例。结果是 IMO 更容易阅读,并且很容易概括为显示两种或多种形式的视图。
def raise_funds_medical_3(request):
args = [request.POST, request.FILES or None] if request.method == "POST" else []
form = RaiseFundsFrom3(*args)
if request.method != "POST" or not form.is_valid():
# unbound form or form not valid
return render(request,'funds/raise_funds_medical_3.html',{'form':form})
# form is valid so do the processing and redirect
check = form.save(commit=False)
check.user = request.user
check.save()
return redirect(<url_pattern>)
如果你想处理>1个表格,测试变成
if request.method != "POST" or any(
[ not form.is_valid(), not form2.is_valid(), ...]):
强制对所有表单进行 .is_valid()
评估,即使第一个表单无效,以便 所有 错误消息显示给用户。
在一个复杂的业务应用程序中,处理一个成功的表单提交可能比这个简单的例子多出好几行代码。把它放在最后,不缩进,与所有样板文件隔离开来,除了 return redirect(...)
,让事情变得容易多了!