Django form.is_valid() не возвращает файл
Я пытаюсь проверить загрузку CSV-файла, проверяя наличие всех ожидаемых заголовков. После того, как я прохожу валидацию на моей форме, возвращаемый файл, похоже, не существует / или недоступен.
Мое мнение:
@login_required
@permission_required('products.report_upload', raise_exception=True)
def uploadPackingNotesView(request):
if request.method == "POST":
form = UploadPackingNotesForm(request.POST, request.FILES)
if form.is_valid():
csv_file = form.cleaned_data['csv_upload']
packing_list = csv.DictReader(io.StringIO(csv_file.read().decode('utf-8')))
packing_list = list(packing_list)
print(packing_list) #prints empty list??
# Pass to Celery for processing
parsePackingNotes.delay(packing_list)
return HttpResponseRedirect(reverse_lazy('product-csv-upload-successful'))
else:
form = UploadPackingNotesForm()
return render(request, 'products/upload-packing-notes.html', {'form': UploadPackingNotesForm})
Моя форма:
class UploadPackingNotesForm(forms.Form):
"""Form used to upload packing notes"""
csv_upload = forms.FileField(label="Select Packing Notes File")
def clean_csv_upload(self):
data = self.cleaned_data['csv_upload']
expected_headers = [
'Branch',
'Carton',
'Delivered',
'SKU',
'PLU',
'Supplier Bar Code',
'Description',
'Size',
'Product Type',
]
packing_list = csv.DictReader(io.StringIO(data.read().decode('utf-8')))
# Check that all required headers are present in the CSV, otherwise return error to frontend
if not set(expected_headers).issubset(packing_list.fieldnames):
raise ValidationError("Couldn't read uploaded CSV")
return data
Я подозреваю, что проблема кроется в строке: csv_file = form.clean_data['csv_upload'] после form.is_valid(), но я не уверен, что нужно использовать, чтобы вернуть подтвержденный файл.
Проблема была в том, что я не понял, что метод .read() не сбрасывает указатель файла (после его использования в функции проверки), поэтому его нужно было сбросить обратно в 0 перед DictReader.
Я изменил блок form.is_valid() на:
if form.is_valid():
uploaded_csv = form.cleaned_data['csv_upload']
uploaded_csv.file.seek(0)
upload_report = list(csv.DictReader(io.StringIO(request.FILES['csv_upload'].read().decode('utf-8'))))
parseEODReport.delay(upload_report)
return HttpResponseRedirect(reverse_lazy('product-csv-upload-successful'))
Строка uploaded_csv.file.seek(0) сбрасывает указатель обратно в начало.
Этот пост помог мне в этом.