Reputation: 943
I have a form that involves uploading a profile picture. I have it working so that I can upload images in the /admin/
interface and display them correctly, but I cannot get my Modelform
to save the image.
Here is what I have:
class Candidate(models.Model):
UserID = models.ForeignKey(User, on_delete=models.CASCADE)
ElectionID = models.ForeignKey(Election, on_delete=models.CASCADE)
Bio = models.CharField(max_length=500, blank=True)
ProfilePicture = models.ImageField(upload_to="profilepics/", null=True, blank=True)
class AddCandidateForm(forms.ModelForm):
class Meta:
model = Candidate
fields = ['ElectionID', 'Bio', 'ProfilePicture']
{% block content %}
<h1>Register as a candidate</h1>
<form method="POST" class="post-form">
{% csrf_token %}
<h2>Select an election:</h2><br>
{{form.ElectionID}}<br>
<h2>Enter your bio:</h2><br>
{{form.Bio}}<br>
<h2>Upload a profile picture:</h2><br>
{{form.ProfilePicture}}<br>
<button type="submit">Register</button>
</form>
{% endblock %}
When I try the view function like so I get the error:
MultiValueDictKeyError at /register/
"'ProfilePicture'"
def add_candidate(request):
if request.method == 'POST':
form = AddCandidateForm(request.POST, request.FILES)
if form.is_valid():
candidate = form.save(commit=False)
candidate = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
return redirect('/home/')
else:
form = AddCandidateForm()
return render(request, 'cand_reg.html', {
"form": form
})
When I remove the offending line, the error goes away.
def add_candidate(request):
if request.method == 'POST':
form = AddCandidateForm(request.POST, request.FILES)
if form.is_valid():
candidate = form.save(commit=False)
# candidate = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
return redirect('/home/')
else:
form = AddCandidateForm()
return render(request, 'cand_reg.html', {
"form": form
})
However, this doesn't actually save the image, so when I try to render it in a separate template, I get an error then.
Can anyone help me understand why the image isn't uploading?
Thanks in advance :)
Upvotes: 1
Views: 473
Reputation: 12106
You must set the ProfilePicture
attribute of the model and not the instance itself (candidate = request.FILES['ProfilePicture']
).
Change to:
candidate = form.save(commit=False)
candidate.ProfilePicture = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
Change your HTML form to accept files as well. Change to: <form method="POST" enctype="multipart/form-data" class="post-form">
. When a form includes file inputs (<input type="file" />
), then it must be encoded differently than it used when it includes only text. More here. If you right-click and inspect the {{form.ProfilePicture}}
you'll see that this is actually a file input.
Extra one:
ProfilePicture
, UserID
etc) in PascalCase. Use snake_case instead (profile_picture
, user_id
etc).Upvotes: 2