Sunday, May 8, 2011

How to write a dynamically generated file to a django FileField in App Engine

I was struggling for days with finding a way to associated a dynamically created csv file with an entity in my django-nonrel project on App Engine.  Then answer finally came as I was looking through the code of the storage module of djangoappenine.  Low and behold, there lies the BlobstoreUploadedFile class, which solved my problem.


from __future__ import with_statement
from djangoappengine.storage import BlobstoreUploadedFile
from google.appengine.ext.blobstore import BlobInfo
from google.appengine.api import files

file_name = files.blobstore.create(mime_type='text/csv')
with files.open(file_name, 'a') as f:
    #do stuff to write your file

files.finalize(file_name)
blobFile = BlobstoreUploadedFile(BlobInfo(files.blobstore.get_blob_key(file_name)), charset="utf-8")
device = Device.objects.get(pk=1)
device.cacheFile.save("filename.csv", blobFile)


Updated to include missing import.  Thanks Ezu.

3 comments:

  1. You're my personal hero of the day! Just there's the reference to BlobInfo to add:

    from google.appengine.ext import blobstore
    or
    from google.appengine.ext.blobstore import BlobInfo

    and it works. I've tried it even on images uploaded throught a classic form (to use uploaders like Plupload) and it works fine! At this point i think to get rid of fileupload module altogether (which is fine, but you're bound to the esoteric upload form).

    Thank you for sharing, you deserve a beer ;)

    ReplyDelete
  2. Note that get_blob_key doesn't always return a valid key due to a bug in App Engine: https://groups.google.com/group/google-appengine/browse_thread/thread/4411a53814bbfd3e

    The solution is:

    while not blob_key:
    time.sleep(1)
    blob_key = files.blobstore.get_blob_key(file_name)

    ReplyDelete