Simran
Simran

Reputation: 633

Django csv file validation in model form clean method

Following is the FileModel to upload a csv file in my Django application:

class File(models.Model):
  uploaded_by = models.ForeignKey(
    User,
    on_delete=models.CASCADE,
  )
  csv_file = models.FileField(
    upload_to='csvfiles/',
  )

On invocation of the /upload_file url pattern, the upload_csv_file view executes as follows:

 def upload_csv_file(request):
   if request.method == 'POST':
      csv_form = CSVForm(request.POST, request.FILES)
      if csv_form.is_valid():
        file_uploaded = csv_form.save(commit=False)
        file_uploaded.uploaded_by = request.user
        csv_form.save()
        return HttpResponse("<h1>Your csv file was uploaded</h1>")

   elif request.method == 'GET':
      csv_form = CSVForm()
      return render(request, './mysite/upload_file.html', {'csv_form': csv_form})

In forms.py I am validating the following:

However I encounter the following error on submitting the file upload button:

  Attribute error: 'bool' object has no attribute 'get'

I am unsure whether the def clean_csv_file(self) is being invoked or not.

There are ways to validate file extension and size within the function-based view, but I would like to validate the file attributes in the ModelForm's clean() method itself.

UPDATE: Solution found

The def clean_csv_file(self) had to return an instance of uploaded_csv_file variable inplace of True.

Also, there is no need for clean() method if clean_field() is present in the ModelForm class.

Upvotes: 0

Views: 1501

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599778

You should have shown the full error and traceback.

Nevertheless, the error caused by what you return from your clean_csv_file. The return value of a clean function must always be the cleaned data itself; for a clean_field method, it must be the cleaned data for that field, and for the general clean method it must be the full cleaned_data dict. So:

def clean_csv_file(self):
   uploaded_csv_file = self.cleaned_data['csv_file']

   if uploaded_csv_file:
     filename = uploaded_csv_file.name
     if filename.endswith(settings.FILE_UPLOAD_TYPE):
        if uploaded_csv_file.size < int(settings.MAX_UPLOAD_SIZE):
            return uploaded_csv_file   # Here
        else:
            raise forms.ValidationError(
                "File size must not exceed 5 MB")
    else:
        raise forms.ValidationError("Please upload .csv extension files only")

  return uploaded_csv_file

Note, your clean method is also wrong, but the corrected version (which would return cleaned_data) does nothing at all, so you should remove the whole thing.

Upvotes: 1

Related Questions