问题
I am trying to use a form to allow users to upload images to projects stored in a database in my Django project, however, I'm currently getting console output that's telling me that the formset
I'm using is not valid...
The view that I'm trying to use to upload the images to a project has been defined with:
def upload_budget_pdfs(request, project_id):
project = Project.objects.get(id=project_id)
print("Value of project in 'upload_budget_pdfs()': ", project)
presentations = project.budget_versions.select_related('meeting').prefetch_related('budget_items', 'cci_items', 'presenters').filter(version_number__isnull=False).annotate(vn=F('version_number') * -1).order_by('presentation_date', 'created', '-vn')
print("Value of presentations in 'upload_budget_pdfs()': ", presentations)
drawing_formset = DrawingUploadFormset(prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created'))
print("Value of drawing_formset in 'upload_budget_pdfs()': ", drawing_formset)
if drawing_formset.is_valid():
print 'Saving drawing_formset'
print "Before", [b.id for b in project.budget_versions.all()]
for drawing_form in drawing_formset:
if drawing_form.instance.budget:
print 'Instance', drawing_form.instance.budget
drawing = drawing_form.save(commit=False)
drawing.budget = drawing_form.instance.budget
drawing.save()
print drawing, [b.id for b in project.budget_versions.all()]
else: print 'Drawing formset not valid.',drawing_formset.errors
budget_formset = BudgetPresentationFormset(request.POST, request.FILES, instance=project, prefix="presentations")
if budget_formset.is_valid() and budget_formset.has_changed():
updated_budget_presentations = budget_formset.save()
elif budget_formset.has_changed(): print 'Budget formset not valid.',budget_formset.errors
return HttpResponseRedirect(reverse('projects:concept', args=[project_id]))
and the console output I'm getting when this view is called is:
("Value of project in 'upload_budget_pdfs()': ", < Project: Test 1 >)
("Value of presentations in 'upload_budget_pdfs()': ", [< Budget: Test 1: Version -1 >, < Budget: Test 1: Version -1 >, < Budget: Test 1: Version 0 >, < Budget: Test 1: Version 0 >, , , , , , , , , , , , , , , , , '...(remaining elements truncated)...'])
("Value of drawing_formset in 'upload_budget_pdfs()': ", < django.forms.formsets.DrawingFormFormSet object at 0x10cee3790 >)
Drawing formset not valid. []
So it's clear that the else
statement in my view is what is being run here, but I'm not sure why, given that the console clearly indicates that the variables all hold the correct data...
What is wrong with the way I am initialising the drawing_formset
variable here? Is the queryset
I'm passing into DrawingUploadFormset(...)
correct? What does is_valid()
actually check?
Edit
I made the change in the accepted answer, so that my declaration of drawing_formset
is now:
drawing_formset = DrawingUploadFormset(request.POST, request.FILES, prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created'))
But it seems I'm now getting an 'Internal Server Error' and MultiValueDictKeyError
on the line:
for drawing_form in drawing_formset: #This line is what's causing the MultiValueDictKeyError
I don't understand why this is? Any suggestions?
回答1:
Your formset does not contain any data. You need to pass request.POST
and request.FILES
as the first and second argument (or as the data
and files
keyword arguments), but only if it is an actual form submission.
If there is no data passed into a form or formset, it is considered unbound, and will return False
without checking for errors.
The usual pattern is to pass them when request.method == 'POST'
, and then validate the formset:
def upload_budget_pdfs(request, project_id):
...
if request.method == 'POST':
drawing_formset = DrawingUploadFormset(request.POST, request.FILES, prefix='drawings', queryset=...)
if drawing_formset.is_valid():
# save formset
return HttpResponseRedirect(...)
else:
drawing_formset = DrawingUploadFormset(prefix='drawings', queryset=...)
return render(...) # Render formset
This will show a blank form on GET, a filled-in form with error messages on an unsuccessful submission, and it will save the formset and redirect on a successful submission.
来源:https://stackoverflow.com/questions/41831332/django-formset-is-not-valid-why-not