Django MultiValueDictKeyError for upload file - django

There has a file upload page for upload file to a object by id in model. However, it shown MultiValueDictKeyError after submitted. I would appreciate if any help.
models.py:
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
items = models.ManyToManyField(OrderItem)
img_upload = models.FileField(upload_to='payment', null=True)
forms.py:
class Upload_File(forms.Form):
class Meta:
model = Order
fields = ('img_upload')
views.py:
def upload_page(request, id):
order = get_object_or_404(Order, id=id)
form = Upload_File(request.POST or None, request.FILES or None)
if request.method == 'POST':
order.img_upload = request.FILES['file']
if form.is_valid():
form.save()
messages.success(request, 'Succeed')
return redirect('user_info')
else:
form = Upload_File()
context = {
'form': form,
}
return render(request, 'upload.html', context)
html:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input class="form-group" type="file" name="file">
<button class="form-group" type="submit">Submit</button>
</form>

Related

Django - uploading files to inline formset

I'm trying to make inline form by using inlineformset_factory but my Image object is not getting saved
models:
class Product(models.Model):
name = models.CharField(max_length=200)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
availability = models.IntegerField()
price = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return self.name
class Image(models.Model):
file = models.ImageField(upload_to="products_images/", default="static/default.png")
uploaded = models.DateTimeField(auto_now_add=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
views:
def CreateNewProductView(request):
context = {}
ProductObj = None
form=ProductForm()
if request.method=='POST':
form = ProductForm(request.POST)
if form.is_valid():
ProductObj = form.save()
print('form is valid, product has been created')
else:
print("form is not valid")
ImageFormset = inlineformset_factory(Product, Image, fields=('file',), extra=1, can_delete=False)
if request.method=='POST':
formset = ImageFormset(request.POST, request.FILES, instance=ProductObj)
if formset.is_valid():
formset.save()
print('formset is valid, product has been created')
else:
print("formset is not valid")
else:
formset = ImageFormset(instance=ProductObj)
if form.is_valid() and formset.is_valid():
return redirect('home')
context = {'form': form, 'formset':formset}
return render(request, 'Ecommerce/test.html', context)
template test.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" action="" id="image-form" style="padding-top:10px;">
{% csrf_token %}
{{form.as_p}}
{{formset}}
{{formset.management_form}}
<button type="submit">submit</button>
</form>
{% endblock content %}
In console I can see "formset is valid, product has been created"
When I printed (request.FILES) i saw <MultiValueDict: {}>. Should it be like that ? In django admin pannel there is no Image objects
What am I doing wrong ?
Add this to your HTML form tag to send files to the server:
enctype="multipart/form-data"
Easy to forget.
Your form will then look like:
<form method="POST" enctype="multipart/form-data" action="" id="image-form" style="padding-top:10px;">
...
Link to Django-docs

How to have pre/post populated id field in django form submission

What I am trying to achieve is to have my "student_id" auto-generated field to be part of the form submission in the sense that the "student_id" field does not have to be manually input in form submission:
The "student_id" field needs to be either pre-generated upon displaying the form or to be generated upon form submission.
I have tried and currently facing error when submitting form as bellow:
KeyError at 'student_id'
Exception Value: 'student_id'
Removing the "student_id = form.cleaned_data['student_id']" syntax in views.py does not help either.
I have the following model, which generates an auto "student_id" field
class Student(models.Model):
student_id = models.AutoField(primary_key=True,unique=True, max_length=10, blank=False)
name = models.CharField(max_length=200, blank=False)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.name
my forms.py:
Class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
'student_id','name', 'first_name', 'last_name'
]
my views.py:
def index(request):
if request.method == 'POST':
form = StudentForm(request.POST, or None)
if form.is_valid():
student_id = form.cleaned_data['student_id']
form.save()
else:
FormError = StudentForm.errors
return redirect(f'/card/{student_id}')
else:
form = StudentForm()
template_name = 'index.html'
context = {
'form' : form,
}
return render(request, template_name, context)
my html:
<form method="POST" action="{% url 'student:index' %}" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
{{ form | crispy }}
</div>
<input type="submit" value="Envoyer" class="btn btn-primary btn-lg btn-block">
</form>
Will appreciate any help

Django is rendering empty template to create new profile instead of submitting form

First some code:
models.py
class Findings(models.Model):
patient = models.ForeignKey(Profile, null=True, blank=True, on_delete=models.CASCADE)
finding_type = models.CharField(max_length=35, null=True)
upload = models.FileField(null=True, blank=True)
date_created = models.DateField(auto_now=True)
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.finding_type
forms.py
class AddFindingForm(ModelForm):
class Meta:
model = Findings
fields = ('finding_type', 'description', 'upload', 'patient')
labels = {
'finding_type' : _('Rodzaj badania'),
'description': _('Opis'),
'upload': _('Dodaj plik'),
}
views.py
def add_finding(request):
form = AddFindingForm()
if request.method == 'POST':
form = UserProfileForm(request.POST, request.FILES)
if form.is_valid():
form = form.save(commit=False)
form.patient = request.user.profile
form.save()
return redirect('profile')
context = {'form': form}
return render(request, 'add_finding.html', context)
template
{% block content %}
<form method="POST" enctype="multipart/form-data" action="">
{% csrf_token %}
{{ form.as_p}}
<button type="submit"> Wyƛlij </button>
</form>
{% endblock %}
So, everytime i'm trying to submit a filled form it displays another form to create new Profile, even if i'm setting patient manually.
The empty form it's displaying is on the same url.
I have no idea why it's doing that...
You are submitting your request.POST data to wrong form. Doing this user's submitted data never gets into AddFindingForm() instead it should be,
def add_finding(request):
form = AddFindingForm()
if request.method == 'POST':
form = AddFindingForm(request.POST, request.FILES) # Change Here
if form.is_valid():
form = form.save(commit=False)
form.patient = request.user.profile
form.save()
return redirect('profile')
context = {'form': form}
return render(request, 'add_finding.html', context)

Django: model doesn't create from models form

I try to create new object from model form, but objects isn't saved.
models.py
class VideoFile(models.Model):
name = models.CharField(max_length=200, blank=True)
file = models.FileField(upload_to="video/", validators=[validate_file_extension])
forms.py
class VideoCreateForm(ModelForm):
class Meta:
model = VideoFile
fields = ['name', 'file']
views.py
def add_video(request):
if request.method == "POST":
form = VideoCreateForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save()
messages.success(request, "saved")
else:
messages.error(request, 'No success!.')
return redirect('vtv:video')
else:
form = VideoCreateForm()
return render(request, "vtv/video_add.html", {'form': form})
templates.html
<h3>Add new video</h3>
<form method = "post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
What's wrong?

How to partially update an object when using modelForm in Django?

I want to let users to add/update caption of their already updated photos without changing any other field of the photo.
Here is the model:
class UserPic(models.Model):
user = models.ForeignKey(User, unique=False)
picfile = ImageWithThumbsField(upload_to= get_uplaod_file_name, sizes=((648,648),(200,200),(1200,1200)))
caption = models.CharField(max_length=200 , blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
likes = models.IntegerField(default=0)
liked_by= models.ForeignKey(Liker, blank=True)
#models.permalink
def get_absolute_url(self):
return ('view_pirate', None, {'user': self.account.user})
def __unicode__(self):
return unicode(self.picfile.name)
views.py
def edit_photo(request, pic_id):
pic = UserPic.objects.get(id=pic_id)
if request.method == 'POST':
if pic.user== request.user:
picform = CaptionForm(request.POST)
if picform.is_valid():
edform = picform.save(commit=False)
edform.caption = request.POST['caption']
edform.save()
message = "caption is uploaded"
else:
edform = CaptionForm()
args = {}
args.update(csrf(request))
args['pic'] = pic
args['pic_id'] = pic_id
#args['form'] = edform
return render_to_response('userpics/photo.html', args,
context_instance= RequestContext(request))
photo.html
<div class="caption">
<form action="{% url "userpics.views.edit_photo" pic.id %}" method="POST">
{% csrf_token %}
{{form.as_ul}}
<input type="submit" value="SEND">
</form>
forms.py:
class CaptionForm(forms.ModelForm):
class Meta:
model= UserPic
fields = ('caption',)
However when I post the form, django still complain that:
MultiValueDictKeyError at /pics/edit/26
"'caption'"
I really got confused as I could not find any resources to deal with this particular problem. So appreciate your hints.
Ok I managed to solved the problem like this:
photo.html
<form action="{% url "userpics.views.edit_photo" pic.id %}" method="POST">
{% csrf_token %}
<input type="text" name="caption" value="{{pic.caption}}">
<input type="submit" value="SEND">
</form>
views.py
def edit_photo(request, pic_id):
pic = UserPic.objects.get(id=pic_id)
if request.method == 'POST':
if pic.user== request.user:
picform = CaptionForm(request.POST)
if picform.is_valid():
pic.caption = request.POST['caption']
pic.save()
message = "caption is uploaded"
else:
edform = CaptionForm(instance=pic)
args = {}
args.update(csrf(request))
args['pic'] = pic
args['pic_id'] = pic_id
return render_to_response('userpics/photo.html', args,
context_instance= RequestContext(request))