Search code examples
djangogoogle-app-enginefile-uploaddjango-nonrel

Uploading and saving files using django nonrel in Google App engine?


According to the official django documentation about uploads, small files are saved to memory and big files are saved to disk.

I would like to know how to save uploaded files to disk? Is it possible?

This is my code so far. But it only works on memory. When I try to write the file to disk, or the file is big in size the app crashes.

views.py

# ...
def spreadsheet_form(request, id = None):
    if is_admin_user(request):
        instance = get_object_or_404(Spreadsheet, id=id) if id is not None else None
        form = SpreadsheetForm(request.POST or None, request.FILES or None, instance=instance)
        if form.is_valid():
            spreadsheet = form.save(commit=False)
            spreadsheet.name = request.POST['name']
            spreadsheet.spreadsheet_file = request.FILES['spreadsheet_file'].name
            spreadsheet.size = request.FILES['spreadsheet_file'].size
            spreadsheet.save()
            handle_uploaded_file(request.FILES['spreadsheet_file'])
            return redirect('/spreadsheets/')
        return render_to_response("pages/spreadsheet_form.html", {"form": form,"id":id},context_instance=RequestContext(request))
    else:
        return redirect('/', False)
# ...
def handle_uploaded_file(f):
    with open(f.name, 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

models.py

# ...
class Spreadsheet(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=256)
    spreadsheet_file = models.FileField(upload_to='spreadsheets/')
    size = models.CharField(max_length=32)
    created_at = models.DateTimeField(auto_now=True)
    # ...
    def __unicode__(self):
        return u'%s' % (self.name )

settings.py

FILE_UPLOAD_HANDLERS = (
    "django.core.files.uploadhandler.MemoryFileUploadHandler",
    "django.core.files.uploadhandler.TemporaryFileUploadHandler",
)
FILE_UPLOAD_MAX_MEMORY_SIZE = 7000000
FILE_UPLOAD_TEMP_DIR = '/tmp'

Thanks in advance


Solution

  • There's no such thing as 'save to disk' in the App Engine world. The closest was Blobstore, and now it's GCS.

    django-nonrel includes a django storage class to upload to Blobstore. Follow this:

    http://www.allbuttonspressed.com/blog/django/2010/06/Uploads-to-Blobstore-and-GridFS-with-Django

    You don't need to fiddle with the FILE_UPLOAD_HANDLERS, the defaults are fine.