Home > other >  Calling form.is_valid() on CSV returning inaccessible / blank file
Calling form.is_valid() on CSV returning inaccessible / blank file

Time:08-03

I'm trying to validate a CSV fileupload by checking all of the expected headers are present. After I pass to validation on my form, the returned file isn't accessible anymore - converting the DictReader object to a list is just now returning an empty list. I'm not receiving any errors.

View:

@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():         
            reader = csv.DictReader(io.StringIO(request.FILES['csv_upload'].read().decode('utf-8')))
            packing_list = list(reader)
            parsePackingNotes.delay(packing_list)

            return HttpResponseRedirect(reverse_lazy('product-csv-upload-successful'))

    else:
        form = UploadPackingNotesForm()

    return render(request, 'products/upload-packing-notes.html', {'form': form})

Form:

class UploadPackingNotesForm(forms.Form):
    """Form used to upload packing notes"""

    csv_upload = FileField(label="Select Packing Notes File", validators=[csvPackingNoteValidator])

Validators

def csvPackingNoteValidator(csv_file):

    packing_list = csv.DictReader(io.StringIO(csv_file.read().decode('utf-8')))

    if not set([
        'Branch',
        'Carton',
        'Delivered',
        'SKU',
        'PLU',
        'Supplier Bar Code',
        'Description',
        'Size',
        'Product Type',
        ]).issubset(packing_list.fieldnames):

        raise ValidationError("Invalid file, select correct report")

Bypassing the form.is_valid() makes it run perfectly, except now I lose validation.

Any ideas? Spent a day and a half trying to troubleshoot and really struggling to find anything on this...?

CodePudding user response:

Issue was that I didnt realise the .read() method does not reset the file pointer (after it had been used in the validation function), so it needed reseting back to 0 prior to the DictReader.

I changed the form.is_valid() block to:

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'))

The line uploaded_csv.file.seek(0) resets the pointer back to the start.

This post helped me out with this.

  • Related