RknRobin RknRobin - 1 month ago 8
Python Question

In Django, how do I get a file path for an uploaded file when uploading?

I am trying to add some validation for user uploaded files. This requires running through a custom script I made called "sumpin", which only takes a filepath as a variable and sends back JSON data that will verify. Everything inside my script is working independently, putting it together where the error occurs.


Since this is file validation, I decided to expand my file_extension validator that was already working.

models.py

from allauthdemo.fileuploadapp.slic3rcheck import sumpin

def user_directory_path_files(instance, filename):
return os.path.join('uploads', str(instance.objectid), filename)


def validate_file_extension(value):
ext = os.path.splitext(value.name)[1]
valid_extensions = ['.stl','.STL']
if not ext in valid_extensions:
raise ValidationError(u'Please upload a .stl file type only')

data = sumpin(value.path)

print (data)


class subfiles(models.Model):
STL = models.FileField(_('STL Upload'),
upload_to=user_directory_path_files, validators=[validate_file_extension])


The error that I get is that the path (value.path) is not valid.


This is the incorrect path because the upload_to tag must change this at a later point. This may be obvious, but I also need to have the file at the filepath location when my script is called. So essentially my questions are...


  1. How can pass the "upload_to" path into my validator to run through my custom script?

  2. Is there a better method to deal with uploaded files, like in the main class with a "save" or "clean" function?


Answer

I've found my own answer, but I'll post it here in case someone runs across this issue in the future.

I was incorrect, a validator wouldn't actually download the file. I need to use a file upload handler, which is shown below.

import os
from django.core.files.storage import default_storage
from allauthdemo.fileuploadapp.slic3rcheck import sumpin



def handle_uploaded_file(f):
    with open(default_storage.path('tmp/'+f.name), 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

    data = sumpin(default_storage.path('tmp/'+f.name))
    os.remove(default_storage.path('tmp/'+f.name))
    return data

then I call this inside my views.py.

from allauthdemo.fileuploadapp.uploadhandler import handle_uploaded_file

@login_required
def STLupload(request):
    # Handle file upload
    if request.method == 'POST':
        formA = ObjectUp(request.POST, request.FILES)
        if formA is_valid():
            data = handle_uploaded_file(request.FILES['STL'])

This will return whatever I called to return within handle_upload_file, which worked perfect for my issues. Hopefully someone will find this useful the future.

Comments