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(...),让事情变得容易多了!