Search code examples
pythondjangodjango-file-upload

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>

on form submit, i do not get any error, but image is not uploaded to the required folder. however, in the raise_funds_medical_3 function within views.py, if i remove instance=request.user, the image gets uploaded but i get following error : NOT NULL constraint failed: funds_campaign.user_id


Solution

  • Your form is a ModelForm for a Campaign, so its instance needs to be a Campaign. Don't assign request.user as its instance!

    Now, your form isn't including the user field which is required to save a Campaign, so you should assign that yourself in the view before saving to the database:

    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
    

    Also you should handle the case where the form isn't valid. This is quite simple, just un-indent the last return in your view function, so that return render(...) is also called in case the form isn't valid.

    Finally, instead of returning a response when the form is valid, it's good practice to redirect to another view. This way, when the user refreshes the page, the form isn't submitted again. Your final code should look like this:

    @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})